【问题标题】:React native state update is not behaving as expected [duplicate]React 本机状态更新未按预期运行 [重复]
【发布时间】:2020-07-25 01:23:09
【问题描述】:

我正在使用包react-native-background-downloader。 我的状态是这样初始化的:

const [downloadFile, setDownloadFile] = useState({});

在我从 api 获取数据之后 我更新了我的状态:

setDownloadFile({
            thumbnail:
              'https://img.youtube.com/vi/J6rVaFzOEP8/maxresdefault.jpg',
            heading: 'Guide To Becoming A Self-Taught Software Developer',
            timing: 123,
            status: 'Staring ...',
          });

然后我使用包从 url 下载视频

const ts = RNBackgroundDownloader.download({
            id: inputUrl,
            url: 'url too long to display',
            destination: `${RNBackgroundDownloader.directories.documents}/test.mp4`,
          });
          setTask(ts);
          ts.begin(async (res) => {
            await setDownloadFile({
              ...downloadFile,
              timing: res / 1024,
            });
            console.log('onbegin', downloadFile);
          });
          ts.progress(async (pr) => {
            await setDownloadFile({
              ...downloadFile,
              status: `Downloading... ${Math.round(pr * 100)}%`,
            });
            console.log('onProgress', downloadFile);
          });
          ts.done(async () => {
            await setDownloadFile({
              ...downloadFile,
              status: 'done',
            });
            console.log('onDone', downloadFile);
          });

我的问题是时间变量中 .begin() 中的状态更新没有在 .progress() 中进行

initially => timing:123,
.begin() => timing: res / 1024,
.progress() => timing:123 (as it was in first place);

【问题讨论】:

    标签: reactjs react-native setstate


    【解决方案1】:

    downloadFile 是一个本地常量。它永远不会改变,这不是setDownloadFile 试图做的。设置状态的目的是告诉组件重新渲染。在下一次渲染时,将创建一个新的局部变量,它会获取新值。

    所以每次你这样做:

    setDownloadFile({
    ...downloadFile
     // etc
    })
    

    ...您正在此闭包中制作downloadFile 的副本。即,在您调用 RNBackgroundDownloader.download 时存在的那个。

    最简单的解决方法是使用 setDownloadFile 的函数版本。您可以将一个函数传递给一个状态设置器,它将以最新状态调用,然后您可以基于该状态建立新状态。例如:

    ts.progress((pr) => {
      setDownloadFile(previous => {
        return {
          ...previous, 
          status: `Downloading... ${Math.round(pr * 100)}%`,
        }
      });
    });
    

    我删除了 async/await,因为设置状态不会返回承诺,所以它没有任何用处。我也删除了日志记录。如果需要,则需要将其放入函数中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-07
      • 1970-01-01
      • 1970-01-01
      • 2020-07-20
      • 1970-01-01
      相关资源
      最近更新 更多