gpt4 book ai didi

useState: setState behaving weirdly in StrictMode(UseState:setState在StrictMode中行为异常)

转载 作者:bug小助手 更新时间:2023-10-25 17:46:46 26 4
gpt4 key购买 nike



I have set the most basic of examples, a Todo List
When i click on the Done button for the first time, it works as expected: the todo item is marked as done: true, and "firing" and "setting" fires only once.
From then on, any button I click triggers the event once but "setting" runs twice so the done state returns to the previous state.

我已经设置了最基本的示例,即TODO列表当我第一次单击Done按钮时,它按预期工作:TODO项被标记为Done:True,并且“Fire”和“Setting”只触发一次。从那时起,我单击的任何按钮都会触发事件一次,但“Setting”会运行两次,这样完成状态就会返回到以前的状态。


codesandbox: https://codesandbox.io/s/optimistic-hermann-m53xs9

Codesandbox:https://codesandbox.io/s/optimistic-hermann-m53xs9


This only happens in StrictMode. I understand what StrictMode means but only regarding useEffect guarding, i had never encountered this behaviour before.

这只会在StrictMode中发生。我理解StrictMode的含义,但仅就Use Effect防护而言,我以前从未遇到过这种行为。


I need to understand why this is happening and how to prevent it.

我需要了解为什么会发生这种情况,以及如何防止它发生。


const TodoList = ({ allTodos }) => {
const [todos, setTodos] = useState(allTodos)

const toggleTodo = id => () => {
console.log('firing')
setTodos(prev => {
console.log('setting')
const newTodos = [...prev]
const todo = newTodos.find(todo => todo.id === id)
todo.done = !todo.done
return newTodos
})
}

return (
<ul>
{todos.map(todo => (
<TodoComponent key={todo.id} todo={todo} toggle={toggleTodo(todo.id)} />
))}
</ul>
)
}

const TodoComponent = ({ todo, toggle }) => {
return (
<li className={todo.done ? 'todo-done' : ''} key={todo.id}>
<span>{todo.text}</span>
<button onClick={toggle}>done</button>
</li>
)
}


更多回答

Hmm I don't know why but when I use my usual way its working though codesandbox.io/s/practical-flower-r5y6dw?file=/src/App.js.

嗯,我不知道为什么,但当我用我通常的方式时,它通过codesandbox.io/s/practical-flower-r5y6dw?file=/src/App.js.起作用了

优秀答案推荐

React documentation tells why double rendering happens in strict mode:

React文档介绍了在严格模式下进行双重渲染的原因:



React assumes that every component you write is a pure function. This means that React components you write must always return the same JSX given the same inputs (props, state, and context).




If a function is pure, running it twice does not change its behavior because a pure function produces the same result every time. However, if a function is impure (for example, it mutates the data it receives), running it twice tends to be noticeable (that’s what makes it impure!) This helps you spot and fix the bug early.




Components breaking this rule behave unpredictably and cause bugs. To help you find accidentally impure code, Strict Mode calls some of your functions (only the ones that should be pure) twice in development. This includes:



  • Functions that you pass to useState, set functions, useMemo, or useReducer



According to last quote, your function that you passed to setState() called twice. You can change your function like this for changing todos once:

根据上一次引用,您传递给setState()的函数调用了两次。您可以像这样更改您的函数以更改待办事项一次:


const toggleTodo = (id) => () => {
setTodos((prev) => {
const newTodos = prev.map((todo) =>
todo.id === id ? { ...todo, done: !todo.done } : todo
);
return newTodos;
});
};

更多回答

Thank you for this answer. I know that it works this way, i had tried it before. I need to understand why it happens when i run the other way as, for many recommendations, when the state derives from the previous state, we should use the setState with the callback version

谢谢你的回答。我知道它是这样工作的,我以前试过。我需要理解为什么当我以另一种方式运行时会发生这种情况,因为对于许多建议,当状态派生自前一个状态时,我们应该将setState与回调版本一起使用

Because of spreading an array returns shallow copy for objects like yours. In my updated code according to your comment for using setState() with callback version, it uses new array for your previous state using map()

由于散布,数组会为像您这样的对象返回浅表副本。在我更新的代码中,根据您在回调版本中使用setState()的注释,它使用map()为您以前的状态使用新的数组

it also works with const newTodos = JSON.parse(JSON.stringify(prev)). the function runs twice as well but the result is what expected

它还可以与const newTodos=JSON.parse(JSON.stringify(Prev))一起使用。该函数的运行速度是预期的两倍,但结果与预期一致

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com