Как я могу обновить состояние компонента на основе его текущего состояния с помощью React Hooks? - PullRequest
0 голосов
/ 10 июля 2019

В моем компоненте я запускаю функцию, которая перебирает ключи в состоянии и обновляет свойства по завершении асинхронных функций.Тем не менее, похоже, что он обновляет состояние до состояния, существовавшего до запуска функции.

Это код моего компонента:

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-адрес изменяется с "queued" на "downloading", а затем обратно на "queued", как только начинается загрузка следующего URL-адреса.

Я думаю, что виновником является эта строка:

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

Я думаю, что progress всегда находится в том же состоянии, в котором он был при выполнении download.

До Hooks я мог передать функцию обновления в setState, но яя не уверен, как повторно использовать существующее состояние в useState хуке.

1 Ответ

0 голосов
/ 10 июля 2019

Вы можете передать функцию обновления так же, как с setState. Итак, в этом коде вы запустите:

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

Это передаст текущее значение progress, что позволит вам обновить состояние на основе его текущего значения.

...