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

React 18中sessionStorage存取异常:results状态无法加载问题

问题分析与解决方案

核心问题根源

你遇到的情况大概率是组件重新挂载后,有其他逻辑(比如API调用)覆盖了从sessionStorage加载的results状态,而filters没有被后续操作覆盖,所以能正常保留sessionStorage的值。具体拆解:

  1. 初始化逻辑与后续状态覆盖冲突
    当从其他路由返回时,BodyComponent重新挂载,空依赖的初始化useEffect会读取sessionStorage并设置results,但如果此时有其他useEffect(比如依赖filters的API调用)在组件挂载后立即触发,API返回的结果会直接覆盖刚从sessionStorage加载的results。而filters因为没有类似的后续覆盖逻辑,所以能正常保留缓存值。

  2. React 18 Strict Mode的潜在影响(开发环境)
    React 18的Strict Mode会在开发环境下重复执行挂载阶段的useEffect和状态更新操作,可能导致sessionStorage的读写出现时序冲突,但这不是核心原因,更多是放大了覆盖问题。


针对性解决方案

方案1:优先使用缓存,避免API无意义覆盖

如果希望组件挂载时优先读取sessionStorage的缓存结果,只有当缓存不存在时才调用API,调整初始化逻辑:

export default function BodyComponent(){
    const [results, setResults] = useState([]);
    const [filters, setFilters] = useState([]);
    
    useEffect(() => {
        // 先读取缓存
        const storedResults = window.sessionStorage.getItem('results');
        const storedFilters = window.sessionStorage.getItem('filters');
        
        if (storedResults) {
            setResults(JSON.parse(storedResults));
        } else {
            // 无缓存时才调用API
            fetchResults(filters).then(res => setResults(res));
        }
        
        if (storedFilters && filters.length === 0) {
            setFilters(JSON.parse(storedFilters));
        }
    }, []);

    useEffect(() => {
        window.sessionStorage.setItem('results', JSON.stringify(results));
    }, [results]);

    return (
        ...
        <FilterComponent filters={filters} setFilters={setFilters}/>
        ...
    )
}

方案2:过滤不必要的API触发

如果需要在filters变化时调用API,但希望避免组件挂载时因缓存的filters触发API覆盖results,可以给API调用添加判断条件:

export default function BodyComponent(){
    const [results, setResults] = useState([]);
    const [filters, setFilters] = useState([]);
    
    useEffect(() => {
        const storedResults = window.sessionStorage.getItem('results');
        const storedFilters = window.sessionStorage.getItem('filters');
        
        if (storedResults) setResults(JSON.parse(storedResults));
        if (storedFilters && filters.length === 0) setFilters(JSON.parse(storedFilters));
    }, []);

    // 仅当filters与缓存值不同时才调用API
    useEffect(() => {
        const storedFilters = window.sessionStorage.getItem('filters');
        if (storedFilters && JSON.stringify(filters) !== storedFilters) {
            fetchResults(filters).then(res => setResults(res));
        }
    }, [filters]);

    useEffect(() => {
        window.sessionStorage.setItem('results', JSON.stringify(results));
    }, [results]);

    return (
        ...
        <FilterComponent filters={filters} setFilters={setFilters}/>
        ...
    )
}

方案3:添加初始化状态锁

通过一个状态标记是否完成缓存加载,避免后续逻辑提前执行:

export default function BodyComponent(){
    const [results, setResults] = useState([]);
    const [filters, setFilters] = useState([]);
    const [isCacheLoaded, setIsCacheLoaded] = useState(false);
    
    useEffect(() => {
        const storedResults = window.sessionStorage.getItem('results');
        const storedFilters = window.sessionStorage.getItem('filters');
        
        if (storedResults) setResults(JSON.parse(storedResults));
        if (storedFilters && filters.length === 0) setFilters(JSON.parse(storedFilters));
        
        setIsCacheLoaded(true);
    }, []);

    // 缓存加载完成后再执行API逻辑
    useEffect(() => {
        if (!isCacheLoaded) return;
        fetchResults(filters).then(res => setResults(res));
    }, [filters, isCacheLoaded]);

    useEffect(() => {
        window.sessionStorage.setItem('results', JSON.stringify(results));
    }, [results]);

    return (
        ...
        <FilterComponent filters={filters} setFilters={setFilters}/>
        ...
    )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 18:12:31