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

为何基于Vite的这段React代码会向服务器发起两次请求?

为什么你的React代码会发起两次请求?

问题根源

这是React 18开发环境下的**Strict Mode(严格模式)**导致的。Vite默认会在开发环境中启用React Strict Mode,它会刻意重复执行useEffect、组件构造函数等代码,目的是帮你检测未正确清理的副作用(比如未取消的订阅、定时器)。

你的代码里,useEffect依赖是空数组,但判断条件是!posts:

  • 第一次执行useEffect时,posts是初始值null,触发getPosts发起请求;
  • Strict Mode会模拟组件卸载后重新挂载,此时posts回到初始的null,第二次执行useEffect时又触发了一次请求,最终导致两次接口调用。

注意:生产环境下Strict Mode会自动禁用,不会出现这个问题。

解决方案

方案1:用状态标记请求是否已发起

添加一个加载状态isLoading,仅在未加载时发起请求,即使useEffect执行两次,第二次时isLoading已变为false,不会重复请求:

import { useEffect, useState } from 'react'
import './App.css'
import axios from 'axios';

function App() {
  const [posts, setPosts] = useState(null);
  const [isLoading, setIsLoading] = useState(true);

  const getPosts = () => {
    axios.get('https://tamoudahost.com/wp/wp-json/wp/v2/posts')
      .then((res) =>{
        setPosts(res.data);
      })
      .finally(() => {
        setIsLoading(false); // 请求完成(成功/失败)都标记为已加载
      })
  }

  useEffect(() => {
    if (isLoading) {
      getPosts();
    }
  }, [isLoading])

  return (
    <div className="App">
      {posts && posts.map((post) => <div key={post.id}>{post.id} : {post.date}</div>)}
    </div>
  )
}

export default App

方案2:用useRef标记请求状态

useRef的值在组件重新挂载时不会重置,适合用来标记是否已经发起过请求:

import { useEffect, useState, useRef } from 'react'
import './App.css'
import axios from 'axios';

function App() {
  const [posts, setPosts] = useState(null);
  const hasRequested = useRef(false);

  useEffect(() => {
    if (!hasRequested.current) {
      axios.get('https://tamoudahost.com/wp/wp-json/wp/v2/posts')
        .then((res) =>{
          setPosts(res.data);
        });
      hasRequested.current = true; // 标记为已发起请求
    }
  }, [])

  return (
    <div className="App">
      {posts && posts.map((post) => <div key={post.id}>{post.id} : {post.date}</div>)}
    </div>
  )
}

export default App

方案3:移除Strict Mode(不推荐)

如果你只是想快速消除开发环境的两次请求,可以修改main.jsx(或main.tsx),去掉<React.StrictMode>的包裹:

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

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

不推荐这个方案,因为Strict Mode能帮你提前发现很多潜在的代码问题。

内容的提问来源于stack exchange,提问作者salim ben yessef

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 11:05:17