在 React 类组件中设置操作前后的加载状态

IT技术 reactjs jsx
2021-04-21 02:39:44

我有发送动作的函数。我想在动作之前和之后显示一个加载器。我知道构成传递给setState. 问题是如何以异步方式更新属性:

handleChange(input) {
    this.setState({ load: true })
    this.props.actions.getItemsFromThirtParty(input)
    this.setState({ load: false })
}

基本上,如果我将此属性作为应用程序状态的一部分(使用 Redux),一切都会很好,但我真的更喜欢将此属性仅带到组件状态。

6个回答

您可以将 setState 包装在 Promise 中并使用 async/await 如下

setStateAsync(state) {
    return new Promise((resolve) => {
      this.setState(state, resolve)
    });
}

async handleChange(input) {
    await this.setStateAsync({ load: true });
    this.props.actions.getItemsFromThirtParty(input);
    await this.setStateAsync({ load: false })
}

来源:ASYNC AWAIT with REACT

我更进一步,做const asyncSetState = instance => newState => new Promise(resolve => instance.setState(newState, resolve));了你可以在任何组件中使用的东西......await asyncSetState(this)({ mystuff: false });
2021-06-01 02:39:44
或者保持简单:-)您可以将其添加到您的实用程序中以重复使用export function setStateAsync(state, that) { return new Promise((resolve) => { that.setState(state, resolve); }); } 并调用await setStateAsync(<new state>, this)
2021-06-19 02:39:44

将其余代码包装在第一个的回调中setState

handleChange(input) {
  this.setState({
    load: true
  }, () => {
    this.props.actions.getItemsFromThirtParty(input)
    this.setState({ load: false })
  })
}

有了这个,你load保证被设置为truebeforegetItemsFromThirtParty被调用并且load被设置回false

这假设您的getItemsFromThirtParty功能是同步的。如果不是,则将其转换为 promise,然后setState在链式then()方法中调用 final

handleChange(input) {
  this.setState({
    load: true
  }, () => {
    this.props.actions.getItemsFromThirtParty(input)
      .then(() => {
        this.setState({ load: false })
      })
  })
}
导出一个函数返回一个接受调度的函数,它返回在 setState 中解析的 Promise .. 像魔术一样工作!谢谢詹姆斯!
2021-06-04 02:39:44
我们如何在 useState 中设置?
2021-06-13 02:39:44
不要忘记在 catch 块中将 load 设置为 false,以防 Promise 被拒绝。
2021-06-17 02:39:44

这是“async-await”setState 的typescript实现:

async function setStateAsync<P, S, K extends keyof S>(
  component: Component<P, S>,
  state:
    ((prevState: Readonly<S>, props: Readonly<P>) => (Pick<S, K> | S | null)) |
    Pick<S, K> |
    S |
    null
) {
  return new Promise(resolve => component.setState(state, resolve));
}
我得到错误: Argument of type '(value: unknown) => void' is not assignable to parameter of type '() => void'.ts(2345)
2021-06-17 02:39:44

这是你可以做的...

  1. 更改您的操作以进行onFetchComplete回调,以及input.
  2. 将您的 handleChange 更改为 -

    handleChange(input) {
        this.setState({ load: true }, ()=>
            this.props.actions.getItemsFromThirtParty(input,
            ()=>this.setState({ load: false }))
        );
    }
    

这将确保动作处理器代码可以调用您的状态更改回调,即使它不是以基于Promise的方式编写的。

捕捉错误 - 绝不能错过。并且不能同意更多关于命名!
2021-06-01 02:39:44
有趣的。但其实更喜欢诺时尚。谢谢你的建议
2021-06-08 02:39:44
是的 Promise 效果更好。在某些情况下,例如 Reflux,不太可能从操作中返回结果,因此您不能在那里使用 Promise。此外,您必须记住抓住它们,否则您将面临永远运行微调器的风险:)。让一些行为返回非Promise,而其他行为Promise也应该清楚地识别出来,比如他们的名字。
2021-06-14 02:39:44

以前的答案不适用于 Hooks。在这种情况下,将第二个参数传递给setState

警告:来自 useState() 和 useReducer() 钩子的状态更新不支持第二个回调参数。要在渲染后执行副作用,请在组件主体中使用 useEffect() 声明它。

正如错误消息所说,useEffect在这种情况下您需要使用代替(另请参阅此讨论以获取更多详细信息)