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

React组件componentDidMount中fetch首次跳转返回空,刷新才正常如何解决?

问题场景

使用React开发预约详情组件对接Express后端时,出现以下异常:通过hashHistory.push("/appointment/" + this.state.id)跳转到详情组件后,首次拉取接口返回空JSON,console.log(json)输出空对象;但刷新页面或直接访问详情页URL时,可以正常拿到数据。

相关代码

Success.js 组件拉取数据逻辑

async componentDidMount() {
        try {
            const response = await fetch(`api/appointments/${this.props.params.id}`)
            if (!response.ok) {
                throw Error(response.statusText);
            }
            const json = await response.json()
            // 首次加载组件时这里输出空对象
            this.setState({ appointmentDetails: json })
        } catch(error) {
            console.log(error)
        }
    }

路由配置

const Routes = (props) => (
  <Router {...props}>
    <Route path="/" component={App} />
    <Route path="/appointment" component={BookAppointment} />
    <Route path="/appointment/:id" component={Success} />
    <Route path="*" component={NotFound} />
  </Router>
);

后端接口逻辑

router.get('/appointments/:param', (req, res) => {
    const identification = new ObjectId(req.params.param)
    Appointment.find({_id: identification}, (err, appointment) => {
      if (err) console.log(err)
      else {
        res.json(appointment)
      }
    })
})
根因定位

跳转前未正确等待预约数据异步入库完成,就执行了路由跳转,导致Success组件componentDidMount触发拉取请求时,对应ID的数据还没写入数据库,因此返回空结果。刷新页面时数据已经完成写入,所以可以正常拉取。

修复方案
  • 优先调整提交预约的异步逻辑:等待后端返回预约创建成功、写入数据库的响应后,再执行路由跳转,不要提前用本地生成的ID跳转。示例修改如下:
// 预约提交逻辑调整示例
async handleSubmit () {
  // 提交预约创建请求
  const submitRes = await fetch('/api/appointments', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(bookInfo)
  })
  const { appointmentId } = await submitRes.json()
  // 拿到后端返回的入库后的ID再跳转
  hashHistory.push(`/appointment/${appointmentId}`)
}
  • 增加兜底重试逻辑:如果存在数据库写入延迟、主从同步延迟等场景,可以在详情页的拉取逻辑中增加重试机制,空结果时间隔一定时间重试,最多重试3次即可:
// 调整后的Success componentDidMount
async componentDidMount(retryTimes = 0) {
  try {
    const response = await fetch(`api/appointments/${this.props.params.id}`)
    if (!response.ok) throw Error(response.statusText);
    const json = await response.json()
    // 结果为空且重试次数未到上限则重试
    if (Object.keys(json).length === 0 && retryTimes < 3) {
      setTimeout(() => this.componentDidMount(retryTimes + 1), 300)
      return
    }
    this.setState({ appointmentDetails: json })
  } catch(err) {
    console.error(err)
  }
}
  • 后端接口兼容优化:查询无结果时返回404状态码而非200+空对象,方便前端明确区分请求状态,做对应提示或重试处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 12:27:04