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

React创建订单组件useEffect重复提交数据问题求助

React useEffect 导致重复创建订单及循环执行问题解决

问题原因

1. 数据库新增2条订单

React 18+的开发环境默认开启严格模式(Strict Mode),这个模式会主动触发两次挂载阶段的副作用(包括useEffect回调),用来检测代码中的潜在问题。你的POST创建订单请求属于副作用,因此会被执行两次,导致数据库生成两条重复订单。生产环境不会有这个问题,Strict Mode仅在开发时生效。

2. fetchOrder函数循环执行

如果fetchOrder没有用useCallback包裹,组件每次重新渲染时都会生成一个全新的函数引用。如果你的useEffect依赖数组中包含了这个不稳定的函数引用,就会导致useEffect反复触发,进而循环调用fetchOrder。

具体解决方案

方案1:解决开发环境重复创建订单问题

用useRef标记请求是否已执行,避免Strict Mode的双重调用:

import { useEffect, useRef, useState } from 'react';

// ...
const isOrderCreated = useRef(false);
const [order, setOrder] = useState(null);

useEffect(() => {
  if (!isOrderCreated.current) {
    fetch(`${process.env.REACT_APP_API_URL}/orders`, {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${localStorage.getItem('token')}`,
        'Content-Type': 'application/json',
      },
    })
    .then(res => res.json())
    .then(data => {
      setOrder(data);
      isOrderCreated.current = true;
    })
    .catch(err => {
      console.error(err);
      isOrderCreated.current = true;
    });
  }
}, []);

方案2:修复fetchOrder循环执行问题

用useCallback包裹fetchOrder,保证函数引用稳定,同时正确设置useEffect依赖:

import { useEffect, useCallback, useState } from 'react';

// ...
const [order, setOrder] = useState(null);

const fetchOrder = useCallback(() => {
  fetch(`${process.env.REACT_APP_API_URL}/orders`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${localStorage.getItem('token')}`,
      'Content-Type': 'application/json',
    },
  })
  .then(res => res.json())
  .then(data => setOrder(data))
  .catch(err => console.error(err));
}, []); // 如果token会动态变化,需要把token加入依赖数组

useEffect(() => {
  fetchOrder();
}, [fetchOrder]);

方案3:更合理的业务逻辑(推荐)

创建订单这类修改数据的操作,不应该在组件挂载时自动执行,而是由用户主动操作触发(比如点击按钮),从根源避免重复请求:

import { useState } from 'react';

// ...
const [order, setOrder] = useState(null);

const handleCreateOrder = () => {
  fetch(`${process.env.REACT_APP_API_URL}/orders`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${localStorage.getItem('token')}`,
      'Content-Type': 'application/json',
    },
  })
  .then(res => res.json())
  .then(data => setOrder(data))
  .catch(err => console.error(err));
};

// 渲染按钮
return (
  <div>
    <button onClick={handleCreateOrder}>创建订单</button>
    {order && <p>订单创建成功:{order.id}</p>}
  </div>
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 11:08:09