reactjs - React 中使用 useCallback 和 useMemo 重新渲染的问题

标签 reactjs react-hooks

我有一个相当简单的组件示例 (Hello.js),它呈现三个组件,每个组件都有不同的 id (Speaker.js)。我有一个从Speaker.js 传回的clickFunction。我认为使用 React.memo 和 React.useCallback 会在只有一个更改时停止所有三个按钮的重新渲染,但遗憾的是,您可以从Speaker.js 中的 console.log 中看到,单击三个按钮中的任何一个都会导致所有三个按钮渲染。

这是 stackblitz 上的问题示例:

https://stackblitz.com/edit/react-dmclqm

Hello.js

import React, { useCallback, useState } from "react";

import Speaker from "./Speaker";

export default () => {
  const speakersArray = [
    { name: "Crockford", id: 101, favorite: true },
    { name: "Gupta", id: 102, favorite: false },
    { name: "Ailes", id: 103, favorite: true },
  ];

  const [speakers, setSpeakers] = useState(speakersArray);

  const clickFunction = useCallback((speakerIdClicked) => {
    var speakersArrayUpdated = speakers.map((rec) => {
      if (rec.id === speakerIdClicked) {
        rec.favorite = !rec.favorite;
      }
      return rec;
    });
    setSpeakers(speakersArrayUpdated);
  },[speakers]);

  return (
    <div>
      {speakers.map((rec) => {
        return (
          <Speaker
            speaker={rec}
            key={rec.id}
            clickFunction={clickFunction}
          ></Speaker>
        );
      })}
    </div>
  );
};

Speaker.js

import React from "react";

export default React.memo(({ speaker, clickFunction }) => {
  console.log(`speaker ${speaker.id} ${speaker.name} ${speaker.favorite}`);
  return (
    <button
      onClick={() => {
        clickFunction(speaker.id);
      }}
    >
      {speaker.name} {speaker.id} {speaker.favorite === true ? "true" : "false"}
    </button>
  );
});

最佳答案

因为当您触发 clickFunction 时,它会更新扬声器,从而导致重新创建此函数,要解决此问题,您需要从 clickFunction 中删除 speakers依赖项并从 setState 回调访问它。 这里是解决方案:

从“react”导入 React, { useCallback, useState,useEffect };

import Speaker from "./Speaker";

export default () => {
  const [speakers, setSpeakers] = useState([
    { name: "Crockford", id: 101, favorite: true },
    { name: "Gupta", id: 102, favorite: false },
    { name: "Ailes", id: 103, favorite: true },
  ]);

  const clickFunction = useCallback((speakerIdClicked) => {
    setSpeakers(currentState=>currentState.map((rec) => {
      if (rec.id === speakerIdClicked) {
        rec.favorite = !rec.favorite;
       return {...rec};
      }
     return rec
    }));
  },[]);
  useEffect(()=>{
    console.log("render")
  })

  return (
    <div>
      {speakers.map((rec) => {
        return (
          <Speaker
            speaker={rec}
            key={rec.id}
            clickFunction={clickFunction}
          ></Speaker>
        );
      })}
    </div>
  );
};

对于扬声器组件:

import React from "react";

export default React.memo(({ speaker, clickFunction }) => {
  return (
    <button
      onClick={() => {
        clickFunction(speaker.id);
      }}
    >
      {speaker.name} {speaker.id} {speaker.favorite === true ? "true" : "false"}
    </button>
  );
});

关于reactjs - React 中使用 useCallback 和 useMemo 重新渲染的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63199752/

相关文章:

ReactJS、react-router 和 socket.io

javascript - 如何禁止 ESLint 将项目添加到 useEffect 的观察者数组中?

javascript - 如何在对象数组上使用 onChange 在 ReactJS 中添加数据

reactjs - 如何在 React 0.14 中的选项标签内使用 FormattedMessage?

javascript - React.js - 使用 this.props 传递实际 URL,而不是链接到本地​​主机?

javascript - 崇高文本中jsx的语法突出显示错误

javascript - map 功能错误: Cannot read property 'map' of undefined in Reactjs

reactjs - 在 React 应用程序中用 useContext 替换 props

reactjs - Firebase 错误 : Failed to get document because the client is offline

reactjs - 如何在类组件中使用 react-redux useSelector?