ReactJS:导航到另一个组件后无法正确检索 localStorageItem
ReactJS: Unable to retrieve properly localStorageItem after navigate to another component
我有这种情况,在用户登录并假设成功后,用户详细信息/用户令牌存储到 localStorage
并将自动导航到仪表板页面,仪表板页面有一些 api 调用和存储在 localStorage
中的那些 api 调用 required/needs token
,我的问题是它无法在 localStorage
中检索这些值,但是当我使用控制台从 localStorage
检查时,key/value 在那里,我注意到,我需要刷新页面才能毫无问题地检索这些详细信息。我怎样才能解决这个问题?导航到另一个组件后能够获得 localStorage
值?
这是我的 index.tsx
代码
ReactDOM.render(
<AuthContextProvider>
<App />
</AuthContextProvider>,
document.getElementById("root")
);
AuthContext 代码:
const AuthContext = React.createContext({
user: "",
isLoggedIn: false,
login: (userdata: any, expirationTime: string) => {},
logout: () => {},
});
export const AuthContextProvider = (props: any) => {
const initialUser = localStorage.getItem("user") || "";
const [userData, setUserData] = useState(initialUser);
const userIsLoggedIn = !!userData;
const logoutHandler = () => {
setUserData("");
localStorage.removeItem("user");
};
const loginHandler = async (
user: any,
expirationTime: string
) => {
localStorage.setItem("user", JSON.stringify(user));
setUserData(user);
};
const contextValue = {
user: userData,
isLoggedIn: userIsLoggedIn,
login: loginHandler,
logout: logoutHandler,
};
return (
<AuthContext.Provider value={contextValue}>
{props.children}
</AuthContext.Provider>
);
};
export default AuthContext;
App.tsx代码
function App() {
const authCtx = useContext(AuthContext);
return (
<BrowserRouter>
<Routes>
{!authCtx.isLoggedIn && (
<Route element={<LoginLayout />}>
<Route index element={<SignInForm />} />
{/*Other links here */}
</Route>
)}
{authCtx.isLoggedIn && (
<Route element={<AdminLayout />}>
<Route path="dashboard" element={<DashboardScreen />} />
{/*Other links here */}
</Route>
)}
<Route path="*" element={<PageNotFound />} />
</Routes>
</BrowserRouter>
);
}
登录码:
try {
await AuthService.login(email, password).then(
(res) => {
authCtx.login(res, "0");
navigate("../dashboard", { replace: true });
},
(error) => {
}
);
} catch (err) {
console.log(err);
}
仪表板代码:
const loadCountOnlineUsers = useCallback(async () => {
try {
await DashboardService.loadCountOnlineUsers().then(
(res) => {
setCntOnlineUsers(res.count);
setflagOnlineUsers(false);
},
(error) => {
setflagOnlineUsers(false);
}
);
} catch (err) {
console.log(err);
setflagOnlineUsers(false);
}
}, [setCntOnlineUsers, setflagOnlineUsers]);
useEffect(() => {
loadCountOnlineUsers();
}, [loadCountOnlineUsers]);
仪表板服务代码:
const config = {
headers: {
"Content-Type": "application/json",
Authorization: AuthHeader(),
},
params: {},
};
const loadCountOnlineUsers = () => {
config["params"] = {};
return axios
.get(API_URL + "api/v1/dashboard-related/online-users", config)
.then((response) => {
return response.data;
});
};
const DashboardService = {
loadCountOnlineUsers,
};
export default DashboardService;
Auth-header代码:
export default function AuthHeader() {
const user = JSON.parse(localStorage.getItem("user") || "{}");
if (user && user.token) {
return "Bearer " + user.token;
} else {
return "";
}
}
问题是 AuthHeader() 中对 localStorage 的检查没有反应性地更新。解决方法是重写 AuthHeader 以接受这样的用户数据:
export default function AuthHeader(user) {
const user = JSON.parse(user || "{}");
if (user && user.token) {
return "Bearer " + user.token;
} else {
return "";
}
}
然后继续将数据管道传输到调用 AuthHeader() 的区域,可能是这样的:
const config = (user) => ({
headers: {
"Content-Type": "application/json",
Authorization: AuthHeader(),
},
params: {},
});
const loadCountOnlineUsers = (user) => {
config["params"] = {};
return axios
.get(API_URL + "api/v1/dashboard-related/online-users", config(user))
.then((response) => {
return response.data;
});
};
const DashboardService = {
loadCountOnlineUsers,
};
最后,在连接到上下文的同时,使用仪表板中的效果对其进行反应式更新:
const authCtx = useContext(AuthContext);
const user = authCtx.user;
const loadCountOnlineUsers = (user) => {
return useCallback(async () => {
try {
await DashboardService.loadCountOnlineUsers(user).then(
(res) => {
setCntOnlineUsers(res.count);
setflagOnlineUsers(false);
},
(error) => {
setflagOnlineUsers(false);
}
);
} catch (err) {
console.log(err);
setflagOnlineUsers(false);
}
}, [setCntOnlineUsers, setflagOnlineUsers]);
}
useEffect(() => {
loadCountOnlineUsers(user);
}, [loadCountOnlineUsers, user]);
我有这种情况,在用户登录并假设成功后,用户详细信息/用户令牌存储到 localStorage
并将自动导航到仪表板页面,仪表板页面有一些 api 调用和存储在 localStorage
中的那些 api 调用 required/needs token
,我的问题是它无法在 localStorage
中检索这些值,但是当我使用控制台从 localStorage
检查时,key/value 在那里,我注意到,我需要刷新页面才能毫无问题地检索这些详细信息。我怎样才能解决这个问题?导航到另一个组件后能够获得 localStorage
值?
这是我的 index.tsx
ReactDOM.render(
<AuthContextProvider>
<App />
</AuthContextProvider>,
document.getElementById("root")
);
AuthContext 代码:
const AuthContext = React.createContext({
user: "",
isLoggedIn: false,
login: (userdata: any, expirationTime: string) => {},
logout: () => {},
});
export const AuthContextProvider = (props: any) => {
const initialUser = localStorage.getItem("user") || "";
const [userData, setUserData] = useState(initialUser);
const userIsLoggedIn = !!userData;
const logoutHandler = () => {
setUserData("");
localStorage.removeItem("user");
};
const loginHandler = async (
user: any,
expirationTime: string
) => {
localStorage.setItem("user", JSON.stringify(user));
setUserData(user);
};
const contextValue = {
user: userData,
isLoggedIn: userIsLoggedIn,
login: loginHandler,
logout: logoutHandler,
};
return (
<AuthContext.Provider value={contextValue}>
{props.children}
</AuthContext.Provider>
);
};
export default AuthContext;
App.tsx代码
function App() {
const authCtx = useContext(AuthContext);
return (
<BrowserRouter>
<Routes>
{!authCtx.isLoggedIn && (
<Route element={<LoginLayout />}>
<Route index element={<SignInForm />} />
{/*Other links here */}
</Route>
)}
{authCtx.isLoggedIn && (
<Route element={<AdminLayout />}>
<Route path="dashboard" element={<DashboardScreen />} />
{/*Other links here */}
</Route>
)}
<Route path="*" element={<PageNotFound />} />
</Routes>
</BrowserRouter>
);
}
登录码:
try {
await AuthService.login(email, password).then(
(res) => {
authCtx.login(res, "0");
navigate("../dashboard", { replace: true });
},
(error) => {
}
);
} catch (err) {
console.log(err);
}
仪表板代码:
const loadCountOnlineUsers = useCallback(async () => {
try {
await DashboardService.loadCountOnlineUsers().then(
(res) => {
setCntOnlineUsers(res.count);
setflagOnlineUsers(false);
},
(error) => {
setflagOnlineUsers(false);
}
);
} catch (err) {
console.log(err);
setflagOnlineUsers(false);
}
}, [setCntOnlineUsers, setflagOnlineUsers]);
useEffect(() => {
loadCountOnlineUsers();
}, [loadCountOnlineUsers]);
仪表板服务代码:
const config = {
headers: {
"Content-Type": "application/json",
Authorization: AuthHeader(),
},
params: {},
};
const loadCountOnlineUsers = () => {
config["params"] = {};
return axios
.get(API_URL + "api/v1/dashboard-related/online-users", config)
.then((response) => {
return response.data;
});
};
const DashboardService = {
loadCountOnlineUsers,
};
export default DashboardService;
Auth-header代码:
export default function AuthHeader() {
const user = JSON.parse(localStorage.getItem("user") || "{}");
if (user && user.token) {
return "Bearer " + user.token;
} else {
return "";
}
}
问题是 AuthHeader() 中对 localStorage 的检查没有反应性地更新。解决方法是重写 AuthHeader 以接受这样的用户数据:
export default function AuthHeader(user) {
const user = JSON.parse(user || "{}");
if (user && user.token) {
return "Bearer " + user.token;
} else {
return "";
}
}
然后继续将数据管道传输到调用 AuthHeader() 的区域,可能是这样的:
const config = (user) => ({
headers: {
"Content-Type": "application/json",
Authorization: AuthHeader(),
},
params: {},
});
const loadCountOnlineUsers = (user) => {
config["params"] = {};
return axios
.get(API_URL + "api/v1/dashboard-related/online-users", config(user))
.then((response) => {
return response.data;
});
};
const DashboardService = {
loadCountOnlineUsers,
};
最后,在连接到上下文的同时,使用仪表板中的效果对其进行反应式更新:
const authCtx = useContext(AuthContext);
const user = authCtx.user;
const loadCountOnlineUsers = (user) => {
return useCallback(async () => {
try {
await DashboardService.loadCountOnlineUsers(user).then(
(res) => {
setCntOnlineUsers(res.count);
setflagOnlineUsers(false);
},
(error) => {
setflagOnlineUsers(false);
}
);
} catch (err) {
console.log(err);
setflagOnlineUsers(false);
}
}, [setCntOnlineUsers, setflagOnlineUsers]);
}
useEffect(() => {
loadCountOnlineUsers(user);
}, [loadCountOnlineUsers, user]);