Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.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
Reactjs React with useCallback和UseMoom中的重新呈现问题_Reactjs_React Hooks - Fatal编程技术网

Reactjs React with useCallback和UseMoom中的重新呈现问题

Reactjs React with useCallback和UseMoom中的重新呈现问题,reactjs,react-hooks,Reactjs,React Hooks,我有一个相当简单的组件Hello.js示例,它呈现了三个组件,每个组件都有一个不同的id Speaker.js。我有一个从Speaker.js传回的clickFunction。我认为使用React.memo和React.useCallback会在只有一个更改时阻止所有三个重新渲染,但遗憾的是,您可以从Speaker.js中的console.log中看到,单击这三个按钮中的任何一个都会导致所有三个渲染 以下是stackblitz的问题示例: 你好 Speaker.js 因为当您启动clickFun

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

以下是stackblitz的问题示例:

你好

Speaker.js

因为当您启动clickFunction时,它会更新扬声器,这会导致重新创建此函数,所以要解决此问题,您需要从clickFunction依赖项中删除扬声器,并从setState callback访问扬声器。 以下是解决方案:

从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>
  );
});
因为当您启动clickFunction时,它会更新扬声器,这会导致重新创建此函数,所以要解决此问题,您需要从clickFunction依赖项中删除扬声器,并从setState callback访问扬声器。 以下是解决方案:

从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>
  );
});

经过进一步思考,我认为我的答案可能并不完全正确:如果没有[演讲者]的依赖性,这将无法按预期工作

两件事:

传递给useCallback的[speakers]依赖项会导致函数在每次speakers更改时重新创建,并且由于回调本身调用setSpeakers,因此它将在每次渲染时重新创建

如果修复1,扬声器组件将根本不会重新渲染,因为它们接收相同的扬声器道具。speaker.favorite已更改的事实不会触发重新渲染,因为speaker仍然是同一个对象。要解决此问题,请使用click函数返回已翻转收藏夹的rec副本,而不是仅在现有对象中切换它:


经过进一步思考,我认为我的答案可能并不完全正确:如果没有[演讲者]的依赖性,这将无法按预期工作

两件事:

传递给useCallback的[speakers]依赖项会导致函数在每次speakers更改时重新创建,并且由于回调本身调用setSpeakers,因此它将在每次渲染时重新创建

如果修复1,扬声器组件将根本不会重新渲染,因为它们接收相同的扬声器道具。speaker.favorite已更改的事实不会触发重新渲染,因为speaker仍然是同一个对象。要解决此问题,请使用click函数返回已翻转收藏夹的rec副本,而不是仅在现有对象中切换它:


谢谢帮了大忙。我仍然得到一个我不理解的警告:第22:5行:React Hook useCallback缺少一个依赖项:“speakers”。包括它或删除依赖项数组react hooks/deps overrideMethod@react\u devtools\u backend.js:2273 printWarnings@webpackHotDevClient.js:138 handleWarnings@webpackHotDevClient.js:143 push../node\u modules/react dev utils/webpackHotDevClient.js.connection.onmessage@webpackHotDevClient.js:210。进一步思考后,我认为我的答案可能不完全正确:如果没有[speakers]依赖项,这将无法按预期工作。请检查我的答案,您可以从setState callback访问当前状态,以便useCallback不会依赖它,因为它可以从依赖项中删除。谢谢。帮了大忙。我仍然得到一个我不理解的警告:第22:5行:React Hook useCallback缺少一个依赖项:“speakers”。包括它或删除依赖项数组react hooks/deps overrideMethod@react\u devtools\u backend.js:2273 printWarnings@webpackHotDevClient.js:138 handleWarnings@webpackHotDevClient.js:143 push../node\u modules/react dev utils/webpackHotDevClient.js.connection.onmessage@webpackHotDevClient.js:210。进一步思考后,我认为我的答案可能不完全正确:如果没有[speakers]依赖项,这将无法按预期工作。请检查我的答案,您可以从setState callback访问当前状态,这样useCallback就不会依赖它,因为它可以从依赖项中删除。谢谢@adel。感谢您抽出额外的时间返回并改进答案。第一次你是如何让它工作的,我一直在苦苦挣扎,但第二次很容易,因为这只是点击功能的改变。这真的是我下一个问题的导论,直到我让这个问题工作了,我才能问这个问题。如果你有时间看一下,它几乎是一样的。谢谢@adel。感谢您抽出额外的时间返回并改进答案。第一次你是如何让它工作的,我一直在苦苦挣扎,但第二次很容易,因为这只是点击功能的改变。这真的是我下一个问题的导论,直到我让这个问题工作了,我才能问这个问题。如果你有时间看一下,它几乎是一样的。
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) {
        return { ...rec, favorite: !rec.favorite }; // <= return a copy of rec
      }
      return rec;
    });
    setSpeakers(speakersArrayUpdated);
  }, []); // <= remove speakers dependency

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