如何使 localStorage 在反应中反应?
How to make localStorage reactive in react?
我正在使用 localStorage 来保存登录时的用户数据。我将其保存为“jwt_data”。
我在单独的 js 文件上创建了一个函数来检索该数据
export const auth = () => {
if(localStorage.getItem('jwt_data')){
return JSON.parse(localStorage.getItem('jwt_data'))
}else{
return false
}
}
并且我有一个导航栏组件与<徽标、搜索栏、下拉列表> 反应。我想在用户注销后隐藏它并在我登录后显示。
我使用代码作为
const auth_user = auth()
........
<>
{auth_user ? (// if logged in..... ) : (// if user is logged out........)
</>
确实奏效了。但问题是它不是反应性的。我需要重新加载网站才能看到效果。
我也试过用其他的比如
const [auth_user, setAuth_user] = useState(false)
useEffect(() => {
if(auth()) {setAuth_user(true)}
else {setAuth_user(false)}
})
与之前的结果相同。
我不知道我哪里错了。其他人建议使用 redux 和东西,这对我的想法和我简单的应用程序来说太复杂了。
我的app.js长这样
import React from 'react';
import Nav from './Nav';
import Home from './Home';
import Login from './Login';
import Logout from './Logout';
function App() {
return (
<div className="App">
<Router>
<Router>
<Nav/>
<Routes>
<Route exact path="/home" element={<Home/>}/>
<Route exact path="/login" element={<Login/>}/>
<Route exact path="/logout" element={<Logout/>}/>
</Routes>
</Router>
</div>
);
}
我登录后,我搬到了家,同时,我想删除导航栏中所有只显示经过身份验证的东西,就像在这种情况下以及其他一般情况下一样。
我在这里遗漏了什么吗?
谢谢您的热心回答。
所以在这种情况下你需要useContext。
在你的app.js
import React, { useContext } from "react";
export const AuthContext = React.createContext(null);
function App() {
const [authContext, setAuthContext] = useState(localStorage.getItem("auth"));
return (
<AuthContext.Provider value={authContext, setAuthContext}>
<Router>
<Nav/>
<Routes>
<Route exact path="/home" element={<Home/>}/>
<Route exact path="/login" element={<Login/>}/>
<Route exact path="/logout" element={<Logout/>}/>
</Routes>
</Router>
</AuthContext.Provider>
);
}
然后在你的 Nav.js
import React, { useContext } from "react";
import { AuthContext } from "./App.js"
function Nav() {
const [authContext, setAuthContext] = useContext(AuthContext);
return (
authContext
? /*Navbar with user stuff*/
: /*Empty Navbar */
)
}
并在您的登录组件中:
import React, { useContext } from "react";
import { AuthContext } from "./App.js"
function Login() {
const [authContext, setAuthContext] = useContext(AuthContext);
const login = () => {
const jwt = "jwt"; // fetch your jwt
localStorage.setItem("auth", jwt)
setAuthContext(jwt);
}
return (
<div>Login form</div>
)
}
并注销:
import React, { useContext } from "react";
import { AuthContext } from "./App.js"
function Logout() {
const [authContext, setAuthContext] = useContext(AuthContext);
const logout = () => {
localStorage.setItem("auth", null)
setAuthContext(null);
}
return (
<button onClick={logout}>Logout button</button>
)
}
我认为这里的问题是你看到 localStorage
作为你的状态,这在 React space 中不太正确。为了让您的组件更新,您需要将此信息保持在您的组件可以订阅的状态。 React 状态 (useState) 或全局状态(redux、context 等)。
那么您的语言环境存储密钥将是一种初始化此状态的方法(例如刷新时)。因此,当登录状态发生变化时,您必须同时更新它们。
既然你想保持简单,最好的方法是在你的 App 组件中创建一个 loggedIn
状态,然后将 loggedIn
状态(Nav 组件)或setLoggedIn
setter(Login/Logout 组件)更新它。
您可以找到有关如何创建反应挂钩的示例,这些挂钩利用 localeStorage
的用法,例如 this one。如果您使用 link 中的 useLocalStorage
或任何其他类似实现,您可以在下面找到您应用程序的代码。
import React from 'react';
import Nav from './Nav';
import Home from './Home';
import Login from './Login';
import Logout from './Logout';
import useLocaleStorage from 'somewhere'
function App() {
const [loggedIn, setLoggedIn] = useLocalStorage('jwt_data', false);
return (
<div className="App">
<Router>
<Router>
<Nav loggedIn={loggedIn} /> // and hide what's need to be hidden
<Routes>
<Route exact path="/home" element={<Home/>}/>
<Route exact path="/login" element={<Login setLoggedIn={setLoggedIn} />}/>
<Route exact path="/logout" element={<Logout setLoggedIn={setLoggedIn} />}/>
</Routes>
</Router>
</div>
);
}
然而,随着您的应用程序变得越来越复杂,您可能会重新考虑将其保持在内部反应状态并使用上下文来避免从 App
组件到其子组件的 prop 钻取。
我正在使用 localStorage 来保存登录时的用户数据。我将其保存为“jwt_data”。 我在单独的 js 文件上创建了一个函数来检索该数据
export const auth = () => {
if(localStorage.getItem('jwt_data')){
return JSON.parse(localStorage.getItem('jwt_data'))
}else{
return false
}
}
并且我有一个导航栏组件与<徽标、搜索栏、下拉列表> 反应。我想在用户注销后隐藏它并在我登录后显示。 我使用代码作为
const auth_user = auth()
........
<>
{auth_user ? (// if logged in..... ) : (// if user is logged out........)
</>
确实奏效了。但问题是它不是反应性的。我需要重新加载网站才能看到效果。
我也试过用其他的比如
const [auth_user, setAuth_user] = useState(false)
useEffect(() => {
if(auth()) {setAuth_user(true)}
else {setAuth_user(false)}
})
与之前的结果相同。 我不知道我哪里错了。其他人建议使用 redux 和东西,这对我的想法和我简单的应用程序来说太复杂了。
我的app.js长这样
import React from 'react';
import Nav from './Nav';
import Home from './Home';
import Login from './Login';
import Logout from './Logout';
function App() {
return (
<div className="App">
<Router>
<Router>
<Nav/>
<Routes>
<Route exact path="/home" element={<Home/>}/>
<Route exact path="/login" element={<Login/>}/>
<Route exact path="/logout" element={<Logout/>}/>
</Routes>
</Router>
</div>
);
}
我登录后,我搬到了家,同时,我想删除导航栏中所有只显示经过身份验证的东西,就像在这种情况下以及其他一般情况下一样。
我在这里遗漏了什么吗? 谢谢您的热心回答。
所以在这种情况下你需要useContext。
在你的app.js
import React, { useContext } from "react";
export const AuthContext = React.createContext(null);
function App() {
const [authContext, setAuthContext] = useState(localStorage.getItem("auth"));
return (
<AuthContext.Provider value={authContext, setAuthContext}>
<Router>
<Nav/>
<Routes>
<Route exact path="/home" element={<Home/>}/>
<Route exact path="/login" element={<Login/>}/>
<Route exact path="/logout" element={<Logout/>}/>
</Routes>
</Router>
</AuthContext.Provider>
);
}
然后在你的 Nav.js
import React, { useContext } from "react";
import { AuthContext } from "./App.js"
function Nav() {
const [authContext, setAuthContext] = useContext(AuthContext);
return (
authContext
? /*Navbar with user stuff*/
: /*Empty Navbar */
)
}
并在您的登录组件中:
import React, { useContext } from "react";
import { AuthContext } from "./App.js"
function Login() {
const [authContext, setAuthContext] = useContext(AuthContext);
const login = () => {
const jwt = "jwt"; // fetch your jwt
localStorage.setItem("auth", jwt)
setAuthContext(jwt);
}
return (
<div>Login form</div>
)
}
并注销:
import React, { useContext } from "react";
import { AuthContext } from "./App.js"
function Logout() {
const [authContext, setAuthContext] = useContext(AuthContext);
const logout = () => {
localStorage.setItem("auth", null)
setAuthContext(null);
}
return (
<button onClick={logout}>Logout button</button>
)
}
我认为这里的问题是你看到 localStorage
作为你的状态,这在 React space 中不太正确。为了让您的组件更新,您需要将此信息保持在您的组件可以订阅的状态。 React 状态 (useState) 或全局状态(redux、context 等)。
那么您的语言环境存储密钥将是一种初始化此状态的方法(例如刷新时)。因此,当登录状态发生变化时,您必须同时更新它们。
既然你想保持简单,最好的方法是在你的 App 组件中创建一个 loggedIn
状态,然后将 loggedIn
状态(Nav 组件)或setLoggedIn
setter(Login/Logout 组件)更新它。
您可以找到有关如何创建反应挂钩的示例,这些挂钩利用 localeStorage
的用法,例如 this one。如果您使用 link 中的 useLocalStorage
或任何其他类似实现,您可以在下面找到您应用程序的代码。
import React from 'react';
import Nav from './Nav';
import Home from './Home';
import Login from './Login';
import Logout from './Logout';
import useLocaleStorage from 'somewhere'
function App() {
const [loggedIn, setLoggedIn] = useLocalStorage('jwt_data', false);
return (
<div className="App">
<Router>
<Router>
<Nav loggedIn={loggedIn} /> // and hide what's need to be hidden
<Routes>
<Route exact path="/home" element={<Home/>}/>
<Route exact path="/login" element={<Login setLoggedIn={setLoggedIn} />}/>
<Route exact path="/logout" element={<Logout setLoggedIn={setLoggedIn} />}/>
</Routes>
</Router>
</div>
);
}
然而,随着您的应用程序变得越来越复杂,您可能会重新考虑将其保持在内部反应状态并使用上下文来避免从 App
组件到其子组件的 prop 钻取。