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

页面刷新时丢失React Context数据的技术问题求助

解决方案

方案一:从URL路由参数获取菜谱ID(推荐)

这是最可靠的方案,符合单页应用的RESTful设计原则,页面刷新时直接从URL提取关键数据,完全不依赖内存状态。

步骤1:修改跳转逻辑,将ID加入URL

在RecipeGridItem组件中,把菜谱ID作为路由参数的一部分传入URL:

const recipeInfoSend = () => {
  // 可选:如果需要同步Context状态可保留此调用
  recipeCtx.addRecipeID(id);
  // 调整URL格式,将ID作为路由参数
  history.push(`/info/${id}/${title.replace(/ /g,"-")}`);
}

步骤2:在详情页通过useParams获取ID

修改RecipeInfoPage,直接从路由参数提取ID,不再依赖Context:

import React, {useState, useEffect} from 'react';
import Container from '../Layout/Container';
import { useParams } from 'react-router-dom';

const RecipeInfoPage = () => {
  const { recipeId } = useParams(); // 从路由获取ID
  const [recipeInfo, setRecipeInfo] = useState({});

  const getRecipeInfo = () => {
    if (!recipeId) return; // 防空判断,避免无效请求
    fetch(`https://api.spoonacular.com/recipes/${recipeId}/information?apiKey=${process.env.REACT_APP_API_KEY}`)
    .then(res => res.json())
    .then(data => setRecipeInfo(data));
  }

  useEffect(() => {
    getRecipeInfo();
  }, [recipeId]);

  return (
    <Container>
      <h1>{recipeInfo.title || '加载中...'}</h1>
      {recipeInfo.summary && <p dangerouslySetInnerHTML={{__html: recipeInfo.summary }}></p>}
    </Container>
  )
}

export default RecipeInfoPage;

步骤3:调整路由配置

确保路由规则匹配新的URL格式(比如在App.js中):

import { Route, Switch } from 'react-router-dom';
import RecipeInfoPage from './pages/RecipeInfoPage';

// ...其他路由配置
<Switch>
  {/* 其他路由 */}
  <Route path="/info/:recipeId/:titleSlug" component={RecipeInfoPage} />
</Switch>

方案二:持久化Context状态到localStorage

如果需要保留Context的状态同步能力,可以将recipeId持久化到本地存储,页面刷新时自动恢复:

修改Context的状态管理逻辑

// 初始化时优先从localStorage读取数据
const [recipeId, setRecipeId] = useState(() => {
  return localStorage.getItem('recipeId') || '';
});

const addRecipeIDHandler = (id) => {
  setRecipeId(id);
  localStorage.setItem('recipeId', id); // 同步存入localStorage
}

// 注意:原代码中provider value缺少addRecipeID方法,需补充
const recipeProviderValue = {
  recipeId: recipeId,
  addRecipeID: addRecipeIDHandler
};

优化详情页逻辑(兼容URL和Context)

即使使用持久化,仍建议优先从URL取ID,避免本地存储与URL数据不一致的问题:

const RecipeInfoPage = () => {
  const recipeCtx = useContext(RecipeContext);
  const { recipeId: urlRecipeId } = useParams();
  // 优先使用URL中的ID,无则 fallback 到Context
  const targetRecipeId = urlRecipeId || recipeCtx.recipeId;
  const [recipeInfo, setRecipeInfo] = useState({});

  const getRecipeInfo = () => {
    if (!targetRecipeId) return;
    fetch(`https://api.spoonacular.com/recipes/${targetRecipeId}/information?apiKey=${process.env.REACT_APP_API_KEY}`)
    .then(res => res.json())
    .then(data => setRecipeInfo(data));
  }

  useEffect(() => {
    getRecipeInfo();
  }, [targetRecipeId]);

  // ...其余渲染代码不变
}

关键问题说明

  1. Context的useState状态存储在内存中,页面刷新后会被重置,因此不能作为详情页获取数据的唯一依赖。
  2. 原Context的recipeProviderValue缺少addRecipeID方法,会导致RecipeGridItem中调用该方法时报错,必须补充。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 02:24:28