You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中如何在promise.then()内正确使用useState?

问题分析与解决方案

核心问题

你的代码存在异步时序不匹配的问题:点击按钮时会同时触发getRules()(异步API请求)和setModalVisible(true)(立即打开模态框)。此时API请求还未返回,rules仍为初始值<h1>hi</h1>,模态框打开后显示的就是这个初始内容。虽然后续API返回后会调用setRules()更新状态,但如果用户没注意到后续更新,就会看起来始终显示初始内容。

另外你的代码存在一个语法错误:const [rules, setRules] React.useState(<h1>hi</h1>); 缺少赋值符号=,正确写法是const [rules, setRules] = React.useState(<h1>hi</h1>);。


解决方案一:等待API返回后再打开模态框

这种方式能确保模态框打开时直接显示正确内容,适合对内容加载速度有信心的场景:

const [rules, setRules] = React.useState(<h1>hi</h1>);
const [modalVisible, setModalVisible] = React.useState(false);

const getRules = () => {
  apicall.promise().then((res) => {
    var rules = null;
    // ... 处理res的逻辑
    rules = <h1>hello</h1>;
    // ...
    return rules;
  }).then((rulesComp) => {
    setRules(rulesComp);
    setModalVisible(true); // 拿到内容后再打开模态框
  });
}

const SvgButton = ({node}: any) => {
  return (
    <foreignObject x="0" y="0" width="20" height="20">
      <div onClick={() => getRules()}>
        <mySVG />
      </div>
    </foreignObject>     
  )
}

return (
  <>
    <div>
      <SvgButton /> is shown here
    </div>

    <Modal
      onDismiss={() => setModalVisible(false)}
      visible={modalVisible}
      closeAriaLabel="Close modal"
      footer="Modal footer"
      header="Modal title"
    >
      {rules}
    </Modal>
  </>
);

解决方案二:先打开模态框,显示加载状态

这种方式用户体验更好,不会让用户等待太久,先显示加载提示,API返回后自动更新内容:

const [rules, setRules] = React.useState(<div>加载中...</div>);
const [modalVisible, setModalVisible] = React.useState(false);

const getRules = () => {
  apicall.promise().then((res) => {
    var rules = null;
    // ... 处理res的逻辑
    rules = <h1>hello</h1>;
    // ...
    return rules;
  }).then((rulesComp) => {
    setRules(rulesComp);
  });
}

const SvgButton = ({node}: any) => {
  return (
    <foreignObject x="0" y="0" width="20" height="20">
      <div onClick={() => {
        setRules(<div>加载中...</div>); // 重置为加载状态
        getRules();
        setModalVisible(true);
      }}>
        <mySVG />
      </div>
    </foreignObject>     
  )
}

return (
  <>
    <div>
      <SvgButton /> is shown here
    </div>

    <Modal
      onDismiss={() => setModalVisible(false)}
      visible={modalVisible}
      closeAriaLabel="Close modal"
      footer="Modal footer"
      header="Modal title"
    >
      {rules}
    </Modal>
  </>
);

内容的提问来源于stack exchange,提问作者chung

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 06:35:18