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

MFA*_*A86 5 javascript reactjs use-state

我在 React useState 钩子上遇到了一些麻烦。我有一个带有复选框按钮的待办事项列表,我想将 'done' 属性更新为 'true',它的 id 与 'clicked' 复选框按钮的 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>
  );
}
Run Code Online (Sandbox Code Playgroud)

我想要的更新状态:

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.
        },
    ]
  })
Run Code Online (Sandbox Code Playgroud)

小智 12

您可以安全地使用 javascript 的数组映射功能,因为它不会修改现有状态,它不喜欢,并且它返回一个新数组。该过程是遍历状态的数组并找到正确的 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
}
Run Code Online (Sandbox Code Playgroud)

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


小智 9

您需要像这样使用扩展运算符:

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

  • [这也会改变当前状态,这是 React 中的反模式。](/sf/ask/2642919821/) (5认同)

小智 9

D. Smith 的答案很好,但可以重构为更具声明性,如下所示。

const toggleDone = (id) => {
 console.log(id);
 setState(state => {
     // loop over the todos list and find the provided id.
     return state.todos.map(item => {
         //gets everything that was already in item, and updates "done" 
         //else returns unmodified item
         return item.id === id ? {...item, done: !item.done} : item
     })
 }); // set state to new object with updated list
}
Run Code Online (Sandbox Code Playgroud)


小智 6

与D. Smith 的答案类似,但更简洁一些:

const toggleDone = (id) => {

  setState(prevState => {
            // Loop over your list
            return prevState.map((item) => {
                // Check for the item with the specified id and update it
                return item.id === id ? {...item, done: !item.done} : item
            })
        })
}
Run Code Online (Sandbox Code Playgroud)