如何在对象数组中使用usestate更新状态?

时间:2020-07-15 15:45:33

标签: javascript reactjs use-state

我在React useState挂钩上遇到了一些麻烦。我有一个带有复选框按钮的待办事项列表,我想将'done'属性更新为'true',该属性具有与'clicked'复选框按钮的ID相同的ID。如果我用console.log的'toggleDone'函数返回正确的ID。但是我不知道如何更新正确的属性。

当前状态:

const App = () => {

  const [state, setState] = useState({
    todos: 
    [
        {
          id: 1,
          title: 'take out trash',
          done: false
        },
        {
          id: 2,
          title: 'wife to dinner',
          done: false
        },
        {
          id: 3,
          title: 'make react app',
          done: false
        },
    ]
  })

  const toggleDone = (id) => {
    console.log(id);
}

  return (
    <div className="App">
        <Todos todos={state.todos} toggleDone={toggleDone}/>
    </div>
  );
}

我想要的更新状态:

const App = () => {

  const [state, setState] = useState({
    todos: 
    [
        {
          id: 1,
          title: 'take out trash',
          done: false
        },
        {
          id: 2,
          title: 'wife to dinner',
          done: false
        },
        {
          id: 3,
          title: 'make react app',
          done: true // if I checked this checkbox.
        },
    ]
  })

4 个答案:

答案 0 :(得分:3)

您可以放心地使用javascript的数组映射功能,因为它不会修改现有状态,而react不喜欢它,它会返回一个新数组。该过程是遍历状态数组并找到正确的ID。更新done布尔值。然后使用更新后的列表设置状态。

const toggleDone = (id) => {
  console.log(id);

  // loop over the todos list and find the provided id.
  let updatedList = state.todos.map(item => 
    {
      if (item.id == id){
        return {...item, done: !item.done}; //gets everything that was already in item, and updates "done"
      }
      return item; // else return unmodified item 
    });

  setState({todos: updatedList}); // set state to new object with updated list
}

编辑:更新了代码以切换item.done,而不是将其设置为true。

答案 1 :(得分:1)

const toggleDone = (id) => {
    console.log(id);
    // copy old state
    const newState = {...state, todos: [...state.todos]};
    // change value
    const matchingIndex = newState.todos.findIndex((item) => item.id == id);
    if (matchingIndex !== -1) {
       newState.todos[matchingIndex] = {
           ...newState.todos[matchingIndex], 
           done: !newState.todos[matchingIndex].done 
       }
    }
    // set new state
    setState(newState);
}

答案 2 :(得分:1)

您需要在此处使用传播运算符Spread operator explanation

现在要更新,我将这样做:

  const toggleDone = (id) => {
    let newState = [...state];
    newState[index].done = true;
    setState(newState])
}

答案 3 :(得分:-1)

我会使用 useState 而不是另一个状态来创建 todos 数组,关键是创建 todos 数组的副本,更新它,并将其设置为新数组。 这是一个工作示例:https://codesandbox.io/s/competent-bogdan-kn22e?file=/src/App.js

const App = () => {
  const [todos, setTodos] = useState([
    {
      id: 1,
      title: "take out trash",
      done: false
    },
    {
      id: 2,
      title: "wife to dinner",
      done: false
    },
    {
      id: 3,
      title: "make react app",
      done: false
    }
  ]);

  const toggleDone = (e, item) => {
    const indexToUpdate = todos.findIndex((todo) => todo.id === item.id);
    const updatedTodos = [...todos]; // creates a copy of the array

    updatedTodos[indexToUpdate].done = !item.done;
    setTodos(updatedTodos);
  };