React TokenContext中useEffect无法存储Spotify登录token问题
问题原因
现有代码逻辑失效是三个点导致的:
- 哈希解析逻辑无容错:手写的字符串分割逻辑中,一旦
find()未匹配到access_token字段,后续调用.split("=")会直接抛出类型错误,中断整个useEffect执行链,后续存储token、清空URL哈希、更新全局状态的代码全部不会运行,授权参数会一直残留在URL上。 - 判断顺序不合理:优先读取localStorage中的值做分支判断,若本地残留空字符串、过期token等无效值,会直接跳过URL哈希解析步骤,无法处理Spotify授权回调后新返回的有效token。
- React 18严格模式下effect会重复执行挂载-卸载流程,原有逻辑未做幂等处理,容易出现状态更新冲突。
修复后的代码
直接替换原有TokenContext.js的内容即可:
import React, { useEffect, useState } from "react"; // token is the state // logOut and logIn is a function for changing the state. export const TokenContext = React.createContext({ token: "", logOut: () => { }, logIn: () => { } }); function getInitialState() { return window.localStorage.getItem('token') || "" } const TokenContextProvider = (props) => { const [token, setToken] = useState(getInitialState); useEffect(() => { const hash = window.location.hash; if (!hash) return; // 用原生API安全解析哈希参数,避免字符串分割的容错问题 const hashParams = new URLSearchParams(hash.substring(1)); const accessToken = hashParams.get("access_token"); if (accessToken) { window.localStorage.setItem("token", accessToken); setToken(accessToken); } // 清空URL上的授权参数,兼容不同浏览器的hash表现 window.history.pushState("", document.title, window.location.pathname + window.location.search); }, []); const logIn = (token) => { window.localStorage.setItem("token", token); setToken(token); }; const logOut = () => { setToken("") window.localStorage.removeItem("token") } return ( <TokenContext.Provider value={{ token, logOut, logIn }} > {props.children} </TokenContext.Provider> ); }; export default TokenContextProvider;
修复点说明
- 用原生
URLSearchParams做哈希参数解析,自带容错能力,不会因为参数格式、字段缺失问题抛错中断逻辑 - 调整判断逻辑:优先解析当前URL的哈希参数,只要拿到有效
access_token就覆盖更新本地存储和全局状态,不会被本地残留的无效值跳过解析流程 - 改用
history.pushState清空URL参数,避免原来设置window.location.hash = ""可能残留#符号的问题,彻底清除URL上的授权返回参数 - 补全
logIn方法的持久化逻辑,修复原逻辑中手动调用登录方法时只更新内存状态、刷新页面就丢失登录态的问题
内容的提问来源于stack exchange,提问作者CesarDlr
相关产品推荐
相关产品推荐

