微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

无法理解反例中的 React 陈旧状态

如何解决无法理解反例中的 React 陈旧状态

我确定我的问题是关于 useCallback 和我在此处使用的 setter 方法 setSpeakersuseState 返回,但我不明白为什么我的示例(如此处和 codeandBox 中列出的)不是正确增加状态。一直返回旧状态,而不是新增加的状态。当我将一个函数传递给 setSpeakers 而不仅仅是一个新状态时,我的示例可以工作(您可以在非工作代码下方看到标记为 THIS CODE WORKS 的注释掉代码

我知道其他人已经写过这方面的文章,我已经阅读了这些文章,但仍然不明白。

沙盒:https://codesandbox.io/s/elated-lichterman-7rejs?file=/pages/index.js

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

//const Speaker = React.memo(({ imageSrc,counter,setCounter }) => {
const Speaker = ({ 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) => {


              // THIS CODE FAILS BECAUSE OF STALE STATE BUT I DON'T GET WHY
              const speakersNew = speakers.map((speaker) => {
                return speaker.id === id
                  ? { ...speaker,clickCount: speaker.clickCount + 1 }
                  : speaker;
              });
              setSpeakers(speakersNew);

              // THIS CODE WORKS
              // setSpeakers(function(speakers) {
              //   const speakersNew = speakers.map((speaker) => {
              //     return speaker.id === id
              //         ? { ...speaker,clickCount: speaker.clickCount + 1 }
              //         : speaker;
              //   });
              //   return speakersNew;
              // });



            },[])}
            key={speaker.id}
          />
        );
      })}
    </div>
  );
}

//
const App = () => {
  const speakersArray = [
    { id: 1124,name: "aaa",clickCount: 0 },{ id: 1530,name: "bbb",{ 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;

解决方法

那是因为 set state 是异步工作的。在未运行的第一个代码中,您设置状态并尝试立即显示它,这将不起作用,因为在设置状态时存在延迟。第二个有效,因为您将回调传递给设置状态,这基本上意味着设置状态并在您使用它时执行此操作。而第一个意味着设置状态,然后再执行此操作。那不是你想要的。这是一个松散的类比,但研究一下 set state 是 aync 的方式和原因,你会有一个更好的主意。干杯。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。