https://codesandbox.io/s/busy-paper-w39kvw?file=/src/components/Comments.js:141-200

const initialState = {
    comments: [
        {
            id: 1,
            username: "Kevin",
            date: "3 hours ago",
            text: "Hello",
            votes: 12,
            upvoted: false,
            downvoted: false,
            comments: []
        }

    ]
}

在我的注释代码中,我有一个useSelector

const { comments } = useSelector(state => state.comments)

这会在每次添加新注释时呈现所有注释

如图所示,使用react dev tools add-on在组件渲染时高亮显示:https://i.gyazo.com/43a93b6d07a5802d91d9f68684e5ded5.mp4

我试着用React.memo来记下这条 comments ,但我不确定为什么不起作用.添加 comments 时,是否仍有停止呈现所有 comments 的方法?

推荐答案

当一个组件被包裹在容器中时,会发生react .memo(),React渲染组件并记忆结果.在下一次渲染之前,如果新的props 相同,React将重新使用记忆结果,跳过下一次渲染.

在下面的代码中,将allComments函数传递给comment组件.

  const allComments = (comments, bg) => {
    const output = comments.map((comment) => {
      return (
        <Comment
          key={comment.id}
          comment={comment}
          allComments={allComments} // the function get's passed as new function object on each rerender
          bg={bg}
        />
      );
    });

    return output;
  };

那么问题是什么?为什么会出现这种行为?

由于函数相等性判断,javascript中的函数被视为一等公民,换句话说,函数是对象.

function factory() {
  return (a, b) => a + b;
}
const sum1 = factory();
const sum2 = factory();
sum1(1, 2); // => 3
sum2(1, 2); // => 3
sum1 === sum2; // => false
sum1 === sum1; // => true

函数sum1sum2共享相同的代码源,但它们是不同的函数对象.比较它们sum1==sum2的计算结果为false.这就是Javascript的工作原理.

在代码中,通过react在每个渲染中创建一个新的函数对象allComments,它最终作为新的props 传递给React.memo().默认情况下,React.memo()会对props 和props 对象进行粗略比较.这就是为什么它会触发新的重播.

现在我们深刻理解了问题所在,以及导致这种行为的原因.

解决方法是用useCallback来包装你的allComments

useCallback的目的是什么?它在渲染之间维护一个函数实例.因此,React.memo()个将起作用.

 const allComments = useCallback((comments, bg) => {
    const output = comments.map((comment) => {
      return (
        <Comment
          key={comment.id}
          comment={comment}
          allComments={allComments}
          bg={bg}
        />
      );
    });

    return output;
  },[]);

Reactjs相关问答推荐

使用useEffect挂钩获取数据

NextJs Form不允许我输入任何输入,

我想删除NextJs中的X轴标签APEXCHARTS

使用`Link`包装`tr`标记会在Next.js中产生水合错误14

禁止直接访问Next.js中的页面,同时允许从应用程序内部访问

ctx.strokeStyle 在 canvas html 5 中不起作用

如何清除过滤器搜索的状态

react 本机屏幕转换

将 useRef 与 useImperativeHandle 一起使用时,React 不会重新渲染

组件安装后调用自定义钩子

提前输入错误:选项类型上不存在属性名称

React - 函数组件 - 点击两次问题处理

我应该如何将字符串作为props 传递给 React 组件?

React - 添加了输入数据但不显示

如何实现 redux 工具包来注册用户?

单击按钮或文本从一个组件移动到另一个组件

当状态改变时如何执行一些动作,但只针对第一次更新?

如果查询不存在,如何返回所有产品?

下拉菜单在 AppBar 中未正确对齐

material uireact ,如何从表格中删除阴影?试图找到 api 但找不到正确的属性