React 18中sessionStorage存取异常:results状态无法加载问题
问题分析与解决方案
核心问题根源
你遇到的情况大概率是组件重新挂载后,有其他逻辑(比如API调用)覆盖了从sessionStorage加载的results状态,而filters没有被后续操作覆盖,所以能正常保留sessionStorage的值。具体拆解:
初始化逻辑与后续状态覆盖冲突
当从其他路由返回时,BodyComponent重新挂载,空依赖的初始化useEffect会读取sessionStorage并设置results,但如果此时有其他useEffect(比如依赖filters的API调用)在组件挂载后立即触发,API返回的结果会直接覆盖刚从sessionStorage加载的results。而filters因为没有类似的后续覆盖逻辑,所以能正常保留缓存值。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
相关产品推荐
相关产品推荐

