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

React中useEffect触发两次,Redux获取后端数据如何仅执行一次?

解决React useEffect执行两次导致重复请求的问题

原因分析

在React 18的开发模式下,StrictMode会刻意让组件挂载→卸载→重新挂载,以此检测组件中是否存在未正确清理的副作用。你的useEffect在组件挂载时触发,所以会执行两次,这是开发环境的正常行为,但生产环境不会出现该情况。

解决方案

方案1:临时关闭StrictMode(不推荐长期使用)

找到项目入口文件(通常是index.js),移除<StrictMode>的包裹:

// 原代码
ReactDOM.createRoot(document.getElementById('root')).render(
  <StrictMode>
    <App />
  </StrictMode>
);

// 修改后
ReactDOM.createRoot(document.getElementById('root')).render(
  <App />
);

这种方式能快速让useEffect只执行一次,但会失去StrictMode的副作用检测能力,不利于排查潜在问题。

方案2:给副作用添加清理逻辑,避免重复请求

使用AbortController取消重复请求,确保即使useEffect执行两次,也只会有一次有效请求:

function App() {
  const dispatch = useDispatch();
  useEffect(() => {
    const controller = new AbortController();
    const fetchPosts = async () => {
      try {
        const response = await fetch('/api/posts', { signal: controller.signal });
        const data = await response.json();
        dispatch(getPosts(data));
      } catch (error) {
        if (error.name !== 'AbortError') {
          console.error('获取帖子失败:', error);
        }
      }
    };
    fetchPosts();

    // 组件卸载时取消请求
    return () => controller.abort();
  }, [dispatch]);

  const posts = useSelector((state) => state.posts);
  console.log(posts);

  return (
    <div>
      <h1>App</h1>
    </div>
  );
}

如果你的getPosts是Redux Toolkit的createAsyncThunk,它本身支持AbortController,可以直接传递signal:

// 定义action时
export const getPosts = createAsyncThunk('posts/getPosts', async (_, { signal }) => {
  const response = await fetch('/api/posts', { signal });
  return response.json();
});

// 组件中使用
useEffect(() => {
  const promise = dispatch(getPosts());
  return () => promise.abort();
}, [dispatch]);

方案3:确保Redux action是幂等的

让getPosts action在处理时,即使被dispatch多次,也不会重复更新store或发送重复请求。比如在后端接口做幂等处理,或者在Redux reducer中判断数据是否已存在,避免重复更新。

注意

生产环境下React不会触发StrictMode的重复挂载行为,上线后不会出现两次请求的问题。开发阶段更推荐使用方案2或3,既能保留StrictMode的检测能力,又能避免无效的重复请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 03:33:30