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

React、NextJS与Redux的Local Storage数据刷新重置问题

问题分析与解决方案

核心问题

你遇到的LocalStorage刷新后重置,本质是Redux状态没有从LocalStorage恢复,反而用初始空值覆盖了存储的数据。原来的逻辑是把Redux状态同步到LocalStorage,但页面刷新后Redux回到初始状态,组件挂载时又把这个空值写回LocalStorage,直接冲掉了之前保存的内容。

修复步骤

1. 让Redux负责状态持久化

修改你的Redux Store配置,在初始化时从LocalStorage加载之前保存的状态,并监听状态变化自动同步到LocalStorage:

import { configureStore } from '@reduxjs/toolkit';
import userReducer from './userSlice';

// 从LocalStorage读取保存的用户状态
const loadSavedState = () => {
  try {
    const savedState = localStorage.getItem('userState');
    return savedState ? JSON.parse(savedState) : undefined;
  } catch (err) {
    // 读取失败时用Reducer的初始状态
    return undefined;
  }
};

// 将状态同步到LocalStorage
const saveStateToLocal = (state) => {
  try {
    // 只保存user切片的数据,避免冗余
    const serializedState = JSON.stringify(state.user);
    localStorage.setItem('userState', serializedState);
  } catch (err) {
    // 忽略存储失败的情况
  }
};

const store = configureStore({
  reducer: {
    user: userReducer,
  },
  // 加载之前保存的状态作为初始值
  preloadedState: {
    user: loadSavedState(),
  },
});

// 监听Redux状态变化,自动保存到LocalStorage
store.subscribe(() => {
  saveStateToLocal(store.getState());
});

export default store;

2. 简化组件逻辑,移除冗余的useLocalStorage

组件只需要和Redux交互,不用直接操作LocalStorage,避免循环更新和覆盖数据:

export default function MyFunction() {
    const settings = {
        apiKey: API_KEY,
        network: Network.ETH_GOERLI
    };
    const alchemy = new Alchemy(settings);
    const contractAddress = CONTRACT_ADDRESS;

    // 直接从Redux获取状态
    const loggedIn = useSelector((state) => state.user.isLoggedIn);
    const owner = useSelector((state) => state.user.walletAddress);
    const nfts = useSelector((state) => state.user.nfts);

    const [pageContent, setPageContent] = useState("An error Occured");
    const dispatch = useDispatch();

    async function getNftsForOwner() {
        const _nfts = [];
        try {
            const nftsIterable = alchemy.nft.getNftsForOwnerIterator(owner);
            for await (const nft of nftsIterable) {
                if (nft.contract.address === contractAddress.toLowerCase()) {
                    _nfts.push(nft);
                }
            }
        } catch (error) {
            console.log(error);
        }
        dispatch(setNfts(_nfts));
    }

    async function signedHandler() {
        if (!window.ethereum) {
            setPageContent("Install Metamask in your browser");
        } else {
            if (window.ethereum.isConnected()) {
                // 只有当Redux中nfts为空时才重新请求,避免重复调用API
                if (nfts.length === 0) {
                    await getNftsForOwner();
                }
                setPageContent(
                    <div>
                        <div><a>NFT Viewer</a></div>
                        <div><a>Your NFT Collection :</a></div>
                        <div><NftList nfts={nfts} /></div>
                    </div>
                );
            } else {
                setPageContent("Connect Wallet");
            }
        }
    }

    useEffect(() => {
        signedHandler();
    }, [loggedIn, owner, nfts]);

    return <div>{pageContent}</div>;
}

关键注意点

  • 确保你的Redux userSlice的初始状态结构,和LocalStorage保存的结构一致,避免加载时出现数据不匹配的问题。
  • 处理LocalStorage读写失败的场景(比如用户浏览器禁用了本地存储),这里用try/catch做了容错。
  • 移除了原代码中useEffect里的storeNft/storeOwner等依赖,避免循环触发更新导致的性能问题和数据覆盖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 13:18:01