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

React应用返回上一页时避免重复设置状态的方法

解决React从详情页返回主页重复发起API请求的问题

你的核心问题是:路由切换导致MainPage组件卸载后重新挂载,触发空依赖的useEffect重复发起API请求。以下是几种无需依赖LocalStorage的解决方案:

方案1:状态提升到路由父组件

将博客数据的状态提升到包裹路由的父组件(比如App),这样路由切换时父组件的状态不会丢失,MainPage重新挂载时直接复用已有数据:

// App.js
import { useState, useEffect } from 'react';
import { Routes, Route } from 'react-router-dom';
import axios from 'axios';
import MainPage from './MainPage';
import BlogDetail from './BlogDetail';

function App() {
  const [blogs, setBlogs] = useState([]);

  useEffect(() => {
    // 仅当数据为空时发起请求
    if (blogs.length === 0) {
      axios.get("/api/blogs/").then((res) => {
        setBlogs(res.data.blogs);
      });
    }
  }, [blogs]);

  return (
    <Routes>
      <Route path="/" element={<MainPage blogs={blogs} />} />
      <Route path="/blog-detail/:id" element={<BlogDetail />} />
    </Routes>
  );
}

// MainPage.js
import { Link } from 'react-router-dom';

function MainPage({ blogs }) {
  return (
    <>
      {blogs.map((res) => (
        <div key={res.id}>
          <b>{res.title}</b>
          <Link to={`blog-detail/${res.id}`}>Blog Detail</Link>
        </div>
      ))}
    </>
  );
}

方案2:使用useRef缓存请求状态

在MainPage组件内用useRef标记是否已完成请求,避免组件重新挂载时重复调用API:

import { useState, useEffect, useRef } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';

function MainPage() {
  const [blogs, setBlogs] = useState([]);
  const hasFetched = useRef(false); // 标记是否已发起过请求

  useEffect(() => {
    if (!hasFetched.current) {
      axios.get("/api/blogs/").then((res) => {
        setBlogs(res.data.blogs);
        hasFetched.current = true;
      });
    }
  }, []);

  // 可选:添加手动刷新函数
  const refreshBlogs = () => {
    axios.get("/api/blogs/").then((res) => {
      setBlogs(res.data.blogs);
    });
  };

  return (
    <>
      {blogs.map((res) => (
        <div key={res.id}>
          <b>{res.title}</b>
          <Link to={`blog-detail/${res.id}`}>Blog Detail</Link>
        </div>
      ))}
      <button onClick={refreshBlogs}>刷新博客</button>
    </>
  );
}

useRef的值在组件卸载后不会被重置,所以返回主页时hasFetched.current仍为true,不会重复请求。

方案3:使用数据请求库(React Query/SWR)

这类库自带请求缓存机制,无需手动处理状态,还支持自动重新验证、重试等功能,适合中大型应用:

以React Query为例:

  1. 安装依赖:
npm install @tanstack/react-query
  1. 配置并使用:
// App.js
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { Routes, Route } from 'react-router-dom';
import MainPage from './MainPage';
import BlogDetail from './BlogDetail';

const queryClient = new QueryClient();

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <Routes>
        <Route path="/" element={<MainPage />} />
        <Route path="/blog-detail/:id" element={<BlogDetail />} />
      </Routes>
    </QueryClientProvider>
  );
}

// MainPage.js
import { useQuery } from '@tanstack/react-query';
import { Link } from 'react-router-dom';
import axios from 'axios';

function MainPage() {
  const { data: blogs = [] } = useQuery({
    queryKey: ['blogs'], // 缓存唯一标识
    queryFn: () => axios.get("/api/blogs/").then(res => res.data.blogs)
  });

  return (
    <>
      {blogs.map((res) => (
        <div key={res.id}>
          <b>{res.title}</b>
          <Link to={`blog-detail/${res.id}`}>Blog Detail</Link>
        </div>
      ))}
    </>
  );
}

React Query会自动缓存请求结果,返回主页时直接复用缓存,无需重复发起API请求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 05:25:44