Javascript 使用React上下文和useReducer防止在todo应用程序中重新呈现未更改的项目
我正在使用context和useReducer创建一个简单的React-todo应用程序,我不确定如何防止每个todo项在其中一个更改时重新呈现。当一个todo更改时,将调度一个操作,从而导致状态更新。具体来说,reducer返回一个状态的新副本,其中一个todo更新,而另一个todo相同 考虑到状态的变化,当一个TODO被更新时,所有TODO都重新呈现是有意义的。但是,我的todo组件将必要的道具传递给每个todo——这些道具不会改变——因此我认为不必改变道具的Javascript 使用React上下文和useReducer防止在todo应用程序中重新呈现未更改的项目,javascript,reactjs,Javascript,Reactjs,我正在使用context和useReducer创建一个简单的React-todo应用程序,我不确定如何防止每个todo项在其中一个更改时重新呈现。当一个todo更改时,将调度一个操作,从而导致状态更新。具体来说,reducer返回一个状态的新副本,其中一个todo更新,而另一个todo相同 考虑到状态的变化,当一个TODO被更新时,所有TODO都重新呈现是有意义的。但是,我的todo组件将必要的道具传递给每个todo——这些道具不会改变——因此我认为不必改变道具的todo组件不会重新渲染。相反,
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;
//来自todos组件
{todo.map(todo=>(
-
))}
//来自todo组件
//handleToggleTodo函数发送“编辑TODO”操作
const EditTodo=({id,description,complete})=>{
//不显示handleToggleTodo函数,该函数将发送“编辑TODO”操作
//并且具有具有todo id和更新的todo描述的有效负载。
返回(
)
我的工作在codesandbox中,您可以使用React
memo()
方法
您需要用react memo包装您的无状态组件,如果道具相同,组件将不会重新呈现
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;
从“React”导入React;
从“/todos_context”导入{useTodosState}”;
从“/Todo”导入Todo;
常数Todos=()=>{
const todos=usetodostate();
返回(
待办事项
{todo.map(todo=>(
-
))}
);
};
const MemoizeTodos=React.memo(Todos);
导出默认MemoizeTodos;
决定更新DOM时,React首先呈现组件,然后
将结果与上一个渲染结果进行比较。如果
结果是不同的,React更新DOM
当前和以前的渲染结果比较快。但是您可以
在某些情况下加快进程
当组件包装在React.memo()
中时,React将呈现
组件并记录结果。在下一次渲染之前,如果
道具是一样的,React重复使用记忆结果,跳过下一个
渲染
事实上,也许我误解了你的回答。当我尝试这样做时,我仍然看到每个todo重新呈现。你可以在上面的codesandbox链接中看到它。你可以使用console.log跟踪呈现。因为我只看到新的todo属性被呈现。谢谢。看起来我实现了我记忆单个
todo
组件时所期望的结果我很高兴听到:)
// 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>
)
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;