我正在使用context和useReducer创建一个简单的React todo应用程序,并且我不确定在其中一项更改时如何防止每个待办事项重新渲染。当一个待办事项更改时,将分派一个动作,从而导致状态更新。具体地说,reduce返回一个待办事项已更新而其他待办事项相同的状态的新副本。
鉴于状态会发生变化,因此在更新一个待办事项时重新渲染所有待办事项是有意义的。但是,我的待办事项组件将必要的道具传递给每个待办事项-并且这些道具不会更改-因此我认为不必更改道具的todo
组件不会重新渲染。取而代之的是,当我使用开发工具并选中突出显示重新渲染的框时,我看到它们全部闪烁。我想念什么?
// from the reducer
case "EDIT_TODO":
return state.map(todo => {
if (todo.id === action.payload.id) {
return {
...todo,
desc: action.payload.value
};
} else {
return todo;
}
});
default:
return state;
// from the todos component
<ul className="TodosApp">
{todos.map(todo => (
<li key={todo.id}>
<Todo
id={todo.id}
complete={todo.complete}
description={todo.desc}
/>
</li>
))}
</ul>
// from the todo component
// handleToggleTodo function dispatches an "EDIT_TODO" action
const EditTodo = ({ id, description, complete }) => {
// not showing the handleToggleTodo function, which dispatches an "EDIT_TODO" action
// and has a payload with the todo id and the updated todo description.
return (
<Fragment>
<input type="checkbox" checked={complete} onChange={handleToggleTodo} />
<input
className="Todo-input"
type="text"
value={description}
onChange={handleChange}
/>
</Fragment>
)
我的工作在codeandbox中,https://codesandbox.io/s/determined-fire-8hirp?fontsize=14
答案 0 :(得分:2)
您可以使用React memo()
方法。
https://dmitripavlutin.com/use-react-memo-wisely/
您需要将无状态组件包装为react备忘录,并且如果props相同,则不会重新渲染该组件。
import React from "react";
import { useTodosState } from "./todos_context";
import Todo from "./todo";
const Todos = () => {
const todos = useTodosState();
return (
<>
<h2>Todos</h2>
<ul className="TodosApp">
{todos.map(todo => (
<li key={todo.id}>
<Todo
id={todo.id}
complete={todo.complete}
description={todo.desc}
/>
</li>
))}
</ul>
</>
);
};
const MemoizeTodos = React.memo(Todos);
export default MemoizeTodos;
在决定更新DOM时,React首先渲染您的组件,然后渲染 将结果与先前的渲染结果进行比较。如果渲染 结果不同,React更新了DOM。
当前与以前的渲染结果比较很快。但是你可以 在某些情况下可以加快流程。
将组件包装在
React.memo()
中时,React会渲染 组件并记住结果。在下一次渲染之前,如果新 道具是一样的,React重复使用记忆的结果,跳过下一个 渲染。