英文:
React Use memo does not update
问题
以下是您提供的内容的翻译:
"I have a todo list. I moved the todolist use memo, so that it updates only when todo is added, but ui does not seem to reflect"
"我有一个待办事项列表。我使用 memo 移动了待办事项列表,以便它只在添加待办事项时更新,但界面似乎没有反映出来。"
代码部分不包括在翻译内。如果您需要进一步的帮助,请随时提问。
英文:
I have a todo list. I moved the todolist use memo, so that it updates only when todo is added, but ui does not seem to reflect
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-html -->
import "./styles.css";
import React from "react";
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<TodoList />
</div>
);
}
const Todo = ({ taskName }) => {
console.log("in here todo");
return <div>{taskName}</div>;
};
const TodoList = () => {
const [todoList, setTodoList] = React.useState([]);
const [iptValue, setIptValue] = React.useState("");
const todoWrapper = React.useMemo(() => {
return (
<>
{(todoList || []).map((item) => (
<Todo taskName={item} key={item} />
))}
</>
);
}, [todoList]);
return (
<div>
{todoWrapper}
<input
type="text"
onChange={(ev) => {
setIptValue(ev.target.value);
}}
/>
<button
onClick={() => {
const todoArr = todoList;
todoArr.push(iptValue);
setIptValue("");
setTodoList(todoArr);
}}
>
Add Notes
</button>
</div>
);
};
<!-- end snippet -->
codepen link: https://codesandbox.io/s/stoic-cloud-phuxsk?file=/src/App.js:0-1082
答案1
得分: 1
React的useMemo
通过Object.is
进行浅层比较
React会使用
Object.is
比较每个依赖项与其先前的值。
而根据MDN Web Docs关于Object.is
的文档,它确定其参数是否相同。其中一个规则是,如果“两者是同一个对象(意思是两个值引用内存中的同一个对象)”,那么这个对象是相同的。
在你的代码中,你调用了setTodoList(todoArr)
,而todoArr
是对todoList
的引用。你对todoArr
所做的唯一更改是调用todoArr.push
。但这并不会在内存中创建一个新的引用。这只是修改了todoList
和todoArr
,因为它们是一样的。
创建一个新数组
你需要做的是创建一个新数组,然后调用setTodoList
。你也可以使用类似Immer或Immutable.js这样的库,允许你“修改”数组和对象,并获得一个新的副本。
// Native react solution
<button
onClick={() => {
const todoArr = [...todoList, iptValue]; // 创建一个新的数组副本并追加iptValue
setTodoList(todoArr);
setIptValue("");
}}
>
添加笔记
</button>
英文:
React's useMemo
does a shallow comparison via Object.is
According to React's documentation for useMemo
,
> React will compare each dependency with its previous value using the Object.is
comparison.
And according to the MDN Web Docs for Object.is
, it determines whether its arguments are the same. One of the rules is that if "both the same object (meaning both values reference the same object in memory)" then the object is the same.
In your code you are calling setTodoList(todoArr)
and todoArr
is a reference to todoList
. The only change you make to todoArr
is the call to todoArr.push
. This does not make a new reference in memory though. This simply modifies todoList
and todoArr
because they are one in the same.
Create a new array
What you need to do is create a new array and then call setTodoList
. You can also use a library like Immer or Immutable.js to allow you to "modify" arrays and objects and get back a new copy instead.
// Native react solution
<button
onClick={() => {
const todoArr = [...todoList, iptValue]; // Makes a new copy of the array and appends iptValue
setTodoList(todoArr);
setIptValue("");
}}
>
Add Notes
</button>
答案2
得分: 1
以下是您要翻译的内容:
可能与此无关,但我刚刚注意到更新模式也是不正确的,当新状态基于/与其原始值相关联时,应通过回调函数进行设置(参见通过回调函数更新状态):
// 点击事件
() => {
setIptValue("");
setTodoList((todoList) => {
const todoArr = [...todoList];
todoArr.push(iptValue);
return todoList
})
}
英文:
It may be unrelated but I just notice that the update pattern is incorrect either, when a new state is based/related with it's original value, it should be set via a callback function:
// onClick
() => {
setIptValue("");
setTodoList((todoList) => {
const todoArr = [...todoList];
todoArr.push(iptValue);
return todoList
})
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论