Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用React上下文和useReducer防止在todo应用程序中重新呈现未更改的项目_Javascript_Reactjs - Fatal编程技术网

Javascript 使用React上下文和useReducer防止在todo应用程序中重新呈现未更改的项目

Javascript 使用React上下文和useReducer防止在todo应用程序中重新呈现未更改的项目,javascript,reactjs,Javascript,Reactjs,我正在使用context和useReducer创建一个简单的React-todo应用程序,我不确定如何防止每个todo项在其中一个更改时重新呈现。当一个todo更改时,将调度一个操作,从而导致状态更新。具体来说,reducer返回一个状态的新副本,其中一个todo更新,而另一个todo相同 考虑到状态的变化,当一个TODO被更新时,所有TODO都重新呈现是有意义的。但是,我的todo组件将必要的道具传递给每个todo——这些道具不会改变——因此我认为不必改变道具的todo组件不会重新渲染。相反,

我正在使用context和useReducer创建一个简单的React-todo应用程序,我不确定如何防止每个todo项在其中一个更改时重新呈现。当一个todo更改时,将调度一个操作,从而导致状态更新。具体来说,reducer返回一个状态的新副本,其中一个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;