如何使用React Hooks根据组件的当前状态更新组件的状态?

时间:2019-07-09 21:54:21

标签: reactjs react-hooks

在我的组件中,我正在运行一个功能,该功能在状态键中进行迭代,并在异步功能完成时更新属性。但是,看起来它正在将状态更新为功能运行之前的状态。

这是我组件的代码:

interface VideoDownloaderProps {
  videos: string[];
}
const VideoDownloader: React.FC<VideoDownloaderProps> = ({ videos }) => {
  const [progress, setProgress] = useState({} as { [key: string]: string });
  const [isDownloading, setIsDownloading] = useState(false);

  async function initialSetup(vids: string[]) {
    const existingKeys = await keys();
    setProgress(
      vids.reduce<{ [key: string]: string }>((a, b) => {
        a[b] = existingKeys.indexOf(b) > -1 ? "downloaded" : "queued";
        return a;
      }, {})
    );
  }

  useEffect(() => {
    initialSetup(videos);
  }, [videos]);

  async function download() {
    setIsDownloading(true);
    const existingKeys = await keys();
    for (const videoUrl of videos) {
      if (existingKeys.indexOf(videoUrl) === -1) {
        setProgress({ ...progress, [videoUrl]: "downloading" });
        const response = await fetch(videoUrl);
        const videoBlob = await response.blob();
        await set(videoUrl, videoBlob);
      }
      setProgress({ ...progress, [videoUrl]: "downloaded" });
    }
    setIsDownloading(false);
  }

  return (
    <div>
      <button disabled={isDownloading} onClick={download}>
        Download Videos
      </button>
      {Object.keys(progress).map(url => (
        <p key={url}>{`${url} - ${progress[url]}`}</p>
      ))}
    </div>
  );
};

从本质上讲,这将遍历URL列表,下载它们,然后将URL的状态设置为"downloaded"。但是,我看到的行为是,下一个URL开始下载后,URL从"queued"切换到"downloading",然后又回到"queued"

我认为罪魁祸首是这条线:

setProgress({ ...progress, [videoUrl]: "downloaded" });

我认为progress始终与执行download时的状态相同。

在使用Hooks之前,我可以将更新程序函数传递给setState,但是我不确定如何在useState Hook中重用现有状态。

1 个答案:

答案 0 :(得分:0)

您可以像使用setState一样传递更新程序功能。因此,在这段代码中,您将运行:

setProgress(progress => ({ ...progress, [videoUrl]: "downloading" }));

这将传递progress的当前值,允许您根据其当前值更新状态。