4

In state, I have an array of list objects and would like to toggle the displayAddTaskForm. Every time I set state, the list that gets clicked gets rearranged and moves to the front of the lists on the UI. I believe I know why this is happening, just not sure of the solution. When I setState in toggleAddTaskForm, toggledList is first and then the other lists. How do I update the toggledList without changing the order of the lists. Here is the code.

this.state = {
      lists: [
        {
          id: 1,
          header: "To Do",
          displayAddTaskForm: false,
        },
        {
          id: 2,
          header: "Working on It",
          displayAddTaskForm: false,
        },
        {
          id: 3,
          header: "Taken Care Of",
          displayAddTaskForm: false,
        }
      ],
      toggleAddTaskForm: (list) => {
        const toggledList = {...list, displayAddTaskForm: !list.displayAddTaskForm}
        const otherLists = this.state.lists.filter(l => l.id !== list.id)
        this.setState({
          lists: [toggledList, ...otherLists]
        })
      },
}

3 Answers 3

3

Putting function in the state is not a common thing. I think you need to seperate that function from state.

You can easily toggle items using Array.map() and checking the clicked item id with the item id. This will not change the order of items.

You can use the following code to toggle only one item:

class App extends Component {
  constructor() {
    super();
    this.state = {
      lists: [
        {
          id: 1,
          header: "To Do",
          displayAddTaskForm: false
        },
        {
          id: 2,
          header: "Working on It",
          displayAddTaskForm: false
        },
        {
          id: 3,
          header: "Taken Care Of",
          displayAddTaskForm: false
        }
      ]
    };
  }
  handleClick = id => {
    let newList = this.state.lists.map(item => {
      if (item.id === id) {
        return {
          ...item,
          displayAddTaskForm: !item.displayAddTaskForm
        };
      } else {
        return {
          ...item,
          displayAddTaskForm: false
        };
      }
    });

    this.setState({ lists: newList });
  };

  render() {
    return (
      <div>
        <ul>
          {this.state.lists.map(({ id, header, displayAddTaskForm }) => {
            return (
              <li key={id} onClick={() => this.handleClick(id)}>
                {header} - Toggle Value: {displayAddTaskForm ? "true" : "false"}
              </li>
            );
          })}
        </ul>
      </div>
    );
  }
}

Playground

Or if you want to be able to toggle every item, you can change the handleClick function like this:

  handleClick = id => {
    let newList = this.state.lists.map(item => {
      if (item.id === id) {
        return {
          ...item,
          displayAddTaskForm: !item.displayAddTaskForm
        };
      } else {
        return {
          ...item
        };
      }
    });

    this.setState({ lists: newList });
  };

Playground

Sign up to request clarification or add additional context in comments.

Comments

1

You could find the index of the list, copy the lists, and insert the modified list into the new lists array at the same index.

toggleAddTaskForm: (list) => {
  const toggledList = {...list, displayAddTaskForm: !list.displayAddTaskForm}
  const newLists = [...this.state.lists];
  newLists[this.state.lists.indexOf(list)] = toggledList;
  this.setState({
    lists: newLists
  })
}

Comments

0

This might help.

lists = [{
    id: 1,
    header: "To Do",
    displayAddTaskForm: false,
}, {
    id: 2,
    header: "Working on It",
    displayAddTaskForm: false,
}, {
    id: 3,
    header: "Taken Care Of",
    displayAddTaskForm: false,
}]

const toggle = (list)=>{
    const toggledList = {
        ...list,
        displayAddTaskForm: true
    }
    const indexOfList = lists.findIndex(({id}) => id === list.id)
    const newLists = [...lists]
    newLists[indexOfList] = toggledList
    setState({
        lists: newLists
    })
}

const setState = (o) => console.log(o)

toggle(lists[1])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.