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

如何通过history.push传递持久化Props?页面刷新后数据丢失的非Redux解决方案咨询

这问题我碰到过好多次了!用history.push传递的state确实会在页面刷新后变成undefined——因为浏览器的路由状态是存在内存里的,刷新页面就会被清空。不想用Redux的话,有几个非常实用的解决方案,我一个个给你说清楚:

方案1:通过URL查询参数传递数据

如果你的数据是简单类型(比如字符串、数字,或者结构不复杂的小对象),可以把数据编码后放到URL的查询参数里。这种方式的好处是URL里直接可见,刷新后不会丢失,而且兼容性拉满。

发送组件代码:

import { useHistory } from 'react-router-dom';

const SenderComponent = () => {
  const history = useHistory();
  const yourData = { id: 123, name: "Shivani" };

  const handleNavigate = () => {
    // 把对象转成字符串并编码,避免URL乱码
    const encodedData = encodeURIComponent(JSON.stringify(yourData));
    history.push(`/target-page?data=${encodedData}`);
  };

  return <button onClick={handleNavigate}>跳转到目标页</button>;
};

接收组件代码:

import { useLocation } from 'react-router-dom';

const TargetComponent = () => {
  const location = useLocation();

  // 解析URL里的参数
  const getTransitData = () => {
    const searchParams = new URLSearchParams(location.search);
    const encodedData = searchParams.get('data');
    if (encodedData) {
      return JSON.parse(decodeURIComponent(encodedData));
    }
    return null;
  };

  const transitData = getTransitData();

  return <div>接收的数据:{JSON.stringify(transitData)}</div>;
};

⚠️ 注意:URL有长度限制(一般是2048字符左右),如果数据太大就别用这个方法了。

方案2:用localStorage/sessionStorage持久化数据

如果你的数据是复杂对象或数组,用本地存储是更合适的选择。把数据存在localStorage(永久保存)或sessionStorage(会话结束后清空)里,目标组件读取后记得及时清理,避免残留数据影响后续操作。

发送组件代码:

import { useHistory } from 'react-router-dom';

const SenderComponent = () => {
  const history = useHistory();
  const yourData = { list: [1,2,3], userInfo: { age: 25 } };

  const handleNavigate = () => {
    // 把数据转成字符串存在sessionStorage里
    sessionStorage.setItem('transitData', JSON.stringify(yourData));
    history.push('/target-page');
  };

  return <button onClick={handleNavigate}>跳转到目标页</button>;
};

接收组件代码:

import { useEffect, useState } from 'react';

const TargetComponent = () => {
  const [transitData, setTransitData] = useState(null);

  useEffect(() => {
    // 读取数据
    const savedData = sessionStorage.getItem('transitData');
    if (savedData) {
      setTransitData(JSON.parse(savedData));
      // 读完立刻删除,避免下次进入页面时拿到旧数据
      sessionStorage.removeItem('transitData');
    }
  }, []);

  return <div>接收的数据:{JSON.stringify(transitData)}</div>;
};

⚠️ 注意:本地存储存的是字符串,所以要记得用JSON.stringify和JSON.parse转换;另外敏感数据别存在这里,因为用户可以在浏览器开发者工具里看到。

方案3:结合React Context管理状态

如果这个数据需要在多个组件之间共享,或者你想统一管理这类临时状态,可以用React Context来代替Redux。Context可以把数据放到全局状态里,刷新后如果需要保留,可以结合本地存储做持久化。

第一步:创建Context

// TransitContext.js
import { createContext, useContext, useState, useEffect } from 'react';

const TransitContext = createContext();

export const TransitProvider = ({ children }) => {
  const [transitData, setTransitData] = useState(null);

  // 组件挂载时从sessionStorage读取数据(应对刷新场景)
  useEffect(() => {
    const savedData = sessionStorage.getItem('transitData');
    if (savedData) {
      setTransitData(JSON.parse(savedData));
      sessionStorage.removeItem('transitData');
    }
  }, []);

  const setTransitAndNavigate = (data, path) => {
    // 存到Context同时存到sessionStorage,应对刷新
    setTransitData(data);
    sessionStorage.setItem('transitData', JSON.stringify(data));
    // 这里可以用history.push,或者让组件自己处理跳转
  };

  return (
    <TransitContext.Provider value={{ transitData, setTransitAndNavigate }}>
      {children}
    </TransitContext.Provider>
  );
};

// 自定义Hook方便使用
export const useTransit = () => useContext(TransitContext);

第二步:在入口文件包裹Provider

// App.js
import { TransitProvider } from './TransitContext';
import { BrowserRouter } from 'react-router-dom';

function App() {
  return (
    <BrowserRouter>
      <TransitProvider>
        {/* 你的路由和组件 */}
      </TransitProvider>
    </BrowserRouter>
  );
}

第三步:发送组件使用

import { useTransit } from './TransitContext';
import { useHistory } from 'react-router-dom';

const SenderComponent = () => {
  const { setTransitAndNavigate } = useTransit();
  const history = useHistory();
  const yourData = { message: "Hello from sender!" };

  const handleNavigate = () => {
    setTransitAndNavigate(yourData);
    history.push('/target-page');
  };

  return <button onClick={handleNavigate}>跳转到目标页</button>;
};

第四步:接收组件使用

import { useTransit } from './TransitContext';

const TargetComponent = () => {
  const { transitData } = useTransit();

  return <div>接收的数据:{JSON.stringify(transitData)}</div>;
};

这个方案适合需要全局共享状态的场景,比Redux轻量很多。

方案4:用路由状态+sessionStorage做自动恢复

如果你还是想保留history.push的state方式,可以在目标组件里做一个自动恢复逻辑——把路由状态存到sessionStorage,刷新后从sessionStorage读回来并更新路由状态。

目标组件代码:

import { useHistory, useLocation } from 'react-router-dom';
import { useEffect } from 'react';

const TargetComponent = () => {
  const history = useHistory();
  const location = useLocation();

  useEffect(() => {
    const STATE_KEY = 'route_transit_state';
    
    // 如果当前路由没有state,尝试从sessionStorage恢复
    if (!location.state) {
      const savedState = sessionStorage.getItem(STATE_KEY);
      if (savedState) {
        // 用replace更新路由状态,不会添加新的历史记录
        history.replace({
          ...location,
          state: JSON.parse(savedState)
        });
        sessionStorage.removeItem(STATE_KEY);
      }
    } else {
      // 如果有state,存到sessionStorage备用
      sessionStorage.setItem(STATE_KEY, JSON.stringify(location.state));
    }

    // 离开页面时清理sessionStorage
    return () => {
      sessionStorage.removeItem(STATE_KEY);
    };
  }, [history, location]);

  return <div>接收的数据:{JSON.stringify(location.state)}</div>;
};

发送组件代码还是原来的:

import { useHistory } from 'react-router-dom';

const SenderComponent = () => {
  const history = useHistory();
  const yourData = { key: "value" };

  const handleNavigate = () => {
    history.push('/target-page', yourData);
  };

  return <button onClick={handleNavigate}>跳转到目标页</button>;
};

这个方案可以保留你原来的跳转方式,同时解决刷新丢失的问题。

总结一下,根据你的数据类型和使用场景选就行:简单数据用URL参数,复杂数据用本地存储,全局共享用Context,想保留原跳转方式就用路由状态+sessionStorage的恢复逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 14:12:37