【问题标题】:How to make react rerender after each one of multiple setStates in one function?如何在一个函数中的多个 setState 中的每一个之后重新渲染?
【发布时间】:2020-03-05 10:14:04
【问题描述】:

我想为我的组件添加“加载”功能。 问题是加载不是异步功能, 所以 setStates 可能会自己批处理。 我们看一下代码:

constructor(props) {
    super(props);
    this.state = {
        loading: false,
        myArray: [1,2,3, ... ,500] //pseudo code (i want to say there is 500 elements, not exactly numbers (cuz i have objects) but to illustrate the problem it doesn't matter)
    };
}

editTable = (howManyElementsToEdit) => {
    if(howManyElementsToEdit > 50) {

        // set loading to true (and make react rerender)
        this.setState({
            loading: true,
        })

        //after react rerendering (the react knows that is in this specified line number in this method?) i want to do the calculations

        const tmp = [...this.state.myArray]; //copy the array
        for(let i=0; i<howManyElementsToEdit; i++) {
            tmp[i] += 1;
        }

        //and now after the modification is done, setState again and loading is false
        this.setState({
            myArray: tmp,
            loading: false,
        })
    } else { //there is no need to loading because not much elements need to be modified

        const tmp = [...this.state.myArray]; //copy the array
        for(let i=0; i<howManyElementsToEdit; i++) {
            tmp[i] += 1;
        }

        this.setState({
            myArray: tmp,
        })

    }   
}

但你可以猜到它不起作用,因为可能会反应“合并”这些 2 个 setStates(当 howManyElementsToEdit > 50 时),这就是为什么我看不到任何加载 当我在渲染中显示 this.state.loading 时。

有人知道我怎样才能实现我的目标吗?

【问题讨论】:

  • 为什么是 -1 ?我不明白。
  • -2 ? ……呃,为什么?我只想加载...

标签: javascript reactjs react-native


【解决方案1】:

React Native 只有一个 js 线程,因此执行昂贵的计算会阻塞您的应用(您将无法与之交互)。

话虽如此,如果您的加载时间足够长以显示微调器,您可能应该异步执行此操作,而不是在 setState() 之后(如果它足够快,那么您可能不需要显示微调器最多 100 毫秒)。

当你调用 setState() 然后做一堆工作时,组件不会在工作完成之前重新渲染,所以两个 setState()-s 不是这里的问题。即使你只有一个也行不通。

幸运的是,react-native 的 ActivityIndicator 组件的动画在原生 UI 线程上运行,因此它不受 js 线程执行昂贵工作的影响。因此,您可以做的是稍微延迟工作以使 setState() 生效。代码如下:

this.setState({
  loading: true,
})
setTimeout(() => {
  const tmp = [...this.state.myArray]; //copy the array
  for(let i=0; i<howManyElementsToEdit; i++) {
    tmp[i] += 1;
  }

  this.setState({
    myArray: tmp,
    loading: false,
  });
}

setTimeout 会将昂贵的工作移到“队列”的后面,因此您的 setState() 将首先重新渲染组件,然后开始进行昂贵的工作。请注意,这仍然会阻塞 js 线程(例如,在工作完成之前您将无法返回),但是如果您在 loadingtrue 时显示 &lt;ActivityIndicator /&gt;,它将不会中断地旋转.

【讨论】:

  • 天哪,谢谢。我知道这不应该发生,但是整个项目中有一种情况可能会发生这种情况(或者当确实有很多数据时)。
猜你喜欢
  • 1970-01-01
  • 2019-12-20
  • 1970-01-01
  • 2019-11-21
  • 1970-01-01
  • 1970-01-01
  • 2019-01-05
  • 2020-08-08
  • 1970-01-01
相关资源
最近更新 更多