【问题标题】:useCallback in React seems to be not letting me update state in parentReact 中的 useCallback 似乎不允许我更新父级中的状态
【发布时间】:2021-02-06 17:04:23
【问题描述】:

我创建了一个简单的示例,说明 useCallback 如何不允许我保留状态更改。当我删除 useCallback 时,我存储在状态中的计数器会按预期更新,但添加 useCallback(我希望这会使所有扬声器项目的重新渲染不重新渲染)不断将我的状态重置回原始状态(0,0 ,0)。

问题代码在codesandbox中:

https://codesandbox.io/s/flamboyant-shaw-2wtqj?file=/pages/index.js

这是一个实际的简单文件示例

import React, { useState, memo, useCallback } from 'react';

const Speaker = memo(({ speaker, speakerClick }) => {
  console.log(speaker.id)
  return (
    <div>
      <span
        onClick={() => {
          speakerClick(speaker.id);
        }}
        src={`speakerimages/Speaker-${speaker.id}.jpg`}
        width={100}
      >{speaker.id} {speaker.name}</span>
      &nbsp;&nbsp;
      <span className="fa fa-star ">&nbsp;&nbsp;{speaker.clickCount}</span>
      &nbsp;
    </div>
  );
});

function SpeakerList({ speakers, setSpeakers }) {
  return (
    <div>
      {speakers.map((speaker) => {
        return (
          <Speaker
            speaker={speaker}
            speakerClick={useCallback((id) => {
              const speakersNew = speakers.map((speaker) => {
                return speaker.id === id
                    ? { ...speaker, clickCount: speaker.clickCount + 1 }
                    : speaker;
              });
              setSpeakers(speakersNew);
            },[])}
            key={speaker.id}
          />
        );
      })}
    </div>
  );
}

//
const App = () => {
  const speakersArray = [
    { id: 1124, name: 'aaa', clickCount: 0 },
    { id: 1530, name: 'bbb', clickCount: 0 },
    { id: 10803, name: 'ccc', clickCount: 0 },
  ];

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

  return (
    <div>
      <h1>Speaker List</h1>
      <SpeakerList speakers={speakers} setSpeakers={setSpeakers}></SpeakerList>
    </div>
  );
};
export default App;

【问题讨论】:

    标签: reactjs react-hooks usecallback


    【解决方案1】:

    首先,你只能在组件体中使用钩子,你不能在speakerClick props 函数声明处包装它。其次,useCallback 将保留原始的 speakers 对象引用,这将是一个陈旧的值。为了解决这个问题,你可以使用 setSpeakers 传递一个回调来代替,你的函数将被当前的 speakers 状态调用:

    function SpeakerList({ speakers, setSpeakers }) {
      const speakerClick = useCallback(
        (id) => {
          // passing a callback avoid using a stale object reference
          setSpeakers((speakers) => {
            return speakers.map((speaker) => {
              return speaker.id === id
                ? { ...speaker, clickCount: speaker.clickCount + 1 }
                : speaker;
            });
          });
        },
        [setSpeakers] // you can add setSpeakers as dependency since it'll remain the same
      );
    
      return (
        <div>
          {speakers.map((speaker) => {
            return (
              <Speaker
                speaker={speaker}
                speakerClick={speakerClick}
                key={speaker.id}
              />
            );
          })}
        </div>
      );
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-16
      • 2021-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多