this.setState 是不是在反应中返回承诺

Posted

技术标签:

【中文标题】this.setState 是不是在反应中返回承诺【英文标题】:Does this.setState return promise in reactthis.setState 是否在反应中返回承诺 【发布时间】:2019-04-23 20:39:25 【问题描述】:

我使我的componentWillMount() 异步。现在我可以使用awaitsetState

这里是示例代码:

componentWillMount = async() => 
  const  fetchRooms  = this.props
  await this.setState( )
  fetchRooms()

所以这里的问题是 this.setState 返回承诺,因为我可以使用 await 吗?

编辑

当我放置 await 时,它会按顺序运行 1, 2, 3 而当我删除 await 时,它会运行 1, 3, 2??

  componentWillMount = async() => 
    const  fetchRooms  = this.props
    console.log(1)
    await this.setState(  => 
      console.log(2)
    )
    console.log(3)
    fetchRooms()
  

【问题讨论】:

setState 不会返回承诺,但您的代码在没有await 之前应该可以正常工作。你想达到什么目的?您还可以使 componentWillMount 方法异步,而不是为每个实例创建一个属性。 async componentWillMount() ... ***.com/questions/53080701/…的可能重复 【参考方案1】:

回答这个问题的更简单方法是我们可以使用 node.js 的预安装 util 库中的 promisify 函数,然后将其与 await 关键字一起使用。

import promisify from 'util';

updateState = promisify(this.setState);
await this.updateState( image: data );

【讨论】:

【参考方案2】:

setState 通常不与 Promise 一起使用,因为很少有这种需要。如果在状态更新 (fetchRooms) 之后调用的方法依赖于更新的状态 (roomId),它可以通过其他方式访问它,例如作为参数。

setState 使用回调并且不返回承诺。由于这很少需要,因此创建未使用的 Promise 会导致开销。

为了返回一个承诺,setState 可以被承诺,正如this answer 中所建议的那样。

发布的代码适用于 await,因为它是一种 hack。 await ...Promise.resolve(...).then(...) 的语法糖。 await 产生一个滴答延迟,允许在状态更新完成后评估下一行,这允许按预期顺序评估代码。这与:

this.setState( roomId: room && room.roomId ? room.roomId : 0 , () => 
  console.log(2)
)

setTimeout(() => 
  console.log(3)
);

无法保证订单在不同条件下保持不变。此外,第一个 setState 回调不是检查状态是否更新的合适位置,这是第二个回调的用途。

【讨论】:

在我看来,对 setState 的承诺的主要需求是主观的:.then 语法非常优雅且易于理解。 (超过第二个可调用的更新后参数) @Xmanoux 它看起来很整洁,但如果它是无意的,一滴滴延迟会干扰 React 生命周期。在 1 个滴答声中可能会发生很多事情。更具体地说,可以卸载组件(这将在 OP 中发生,因为 componentWillMount 不应该是异步的)。通常,promise 控制流存在一个已知问题,因为 promise 不可取消且不了解组件生命周期。如果在不需要的地方使用 Promise,它就会变得更加突出。【参考方案3】:

您可以承诺 this.setState 以便您可以将 React API 用作承诺。这就是我让它工作的方式:

class LyricsGrid extends Component 

  setAsyncState = (newState) =>
    new Promise((resolve) => this.setState(newState, resolve));

稍后,我使用标准 Promise API 调用 this.setAsyncState

this.setAsyncState( lyricsCorpus, matrix, count )
  .then(foo1)
  .then(foo2)
  .catch(err => console.error(err))

【讨论】:

您不必绑定箭头函数方法,因此您甚至不需要手动编写构造函数。它们会自动捕获周围上下文的 this。 他们没有内部this,所以它只使用外部this 警告:来自 useState() 和 useReducer() Hooks 的状态更新不支持第二个回调参数。要在渲染后执行副作用,请在组件主体中使用 useEffect() 声明它。【参考方案4】:

不要认为setState 会返回Promise,但您始终可以这样做

 await new Promise( ( resolve ) => 
     this.setState( 
         data:null,
     , resolve )
 )

或者你可以做一些这样的实用功能

const setStateAsync = ( obj, state ) => 
    return new Promise( ( resolve ) =>
        obj.setState( state , resolve )
    )

并像这样在 React.Component 中使用它:

await setStateAsync(this,some:'any')

【讨论】:

【参考方案5】:

你可以简单地为 setState 自定义一个 Promise

  componentWillMount = async () => 
    console.log(1);
    await this.setRooms();
    console.log(3);
  ;

  setRooms = () => 
    const  fetchRooms  = this.props;
    return fetchRooms().then(( room ) => 
      this.setState( roomId: room && room.roomId ? room.roomId : 0 , _ =>
        console.log(2)
      );
    );
  ;

或者

  setRooms = async () => 
    const  fetchRooms  = this.props;
    const  room  = await fetchRooms();

    return new Promise(resolve => 
      this.setState( roomId: room && room.roomId ? room.roomId : 0 , _ =>
        resolve()
      );
    );
  ;

希望这个帮助=D

【讨论】:

【参考方案6】:

setState 不返回承诺。

setState 有一个回调。

this.setState(
    ...this.state,
    key: value,
, () => 
    //finished
);

【讨论】:

如果使用钩子,setState 没有回调。 @HasanSefaOzalp 但是你可以使用effect 警告:来自 useState() 和 useReducer() Hooks 的状态更新不支持第二个回调参数。要在渲染后执行副作用,请在组件主体中使用 useEffect() 声明它。 @Danish 我的回答是关于基于分类的组件而不是钩子。【参考方案7】:

它不返回承诺。

您可以在任何表达式前面加上await 关键字。如果该表达式的计算结果不是一个 Promise,它就没有效果。

setState 接受回调。

【讨论】:

不,我可以看到变化。让我再次澄清你的问题。当我将await 放在this.setState 前面时,它会停止代码。我通过在this.setState 之前和之后放置日志来检查它。这就是我在这里提出问题的原因。

以上是关于this.setState 是不是在反应中返回承诺的主要内容,如果未能解决你的问题,请参考以下文章

承诺解决后未触发reactjs render() this.setState 被重新分配

如何正确删除操作?

反应中嵌套数组中的setState

在功能组件中使用回调对 setState 进行反应

是否可以在反应渲染函数中返回空?

反应路由器和setState冲突