我正在制作一个现代堆栈应用程序,当前我正在尝试在登录路径和主页之间进行切换,这取决于您是否登录。但是,这仅在刷新页面后才起作用,是否有任何方法可以使它工作而不必刷新页面?
App.js
{!localStorage.getItem('token') ? (
<Redirect exact from='/' to='/login' />
):
<>
<Navbar />
<Redirect to='/' />
</>
}
答案 0 :(得分:0)
对本地存储的更改做出反应-最好-是一种怪异的方法。实际上,重新渲染组件的唯一方法是通过其接收的更改道具,或通过useState
使用组件状态。
我将编写这段虚构的代码来说明我的观点:
import React, { useState } from 'react'
import { useHistory } from 'react-router-dom'
// ...
const LoginPage = _props {
const [token, setToken] = useState(localStorage.getItem('token'))
if (token) {
return <Redirect to='/' />
}
// I have no idea how you login your users
return (
<div>
<LoginForm onToken={setToken} />
</div>
)
}
如果您需要组件A对组件B所做的更改作出反应,而这两个更改都不是另一个的直接子代,则需要全局状态。
全局状态类似于组件状态,因为对它的更改应触发依赖于它的组件的重新渲染。但这是 global ,而不是特定组件的本地。
要实现这一点,可以使用类似redux的复杂解决方案,但是您可以使用React Context实现一个非常简单的版本:
// src/providers/GlobalStateProvider.js
import React, { createContext, useContext, useState } from 'react'
const Context = createContext()
const GlobalStateProvider = ({ children }) => {
const [token, doSetToken] = useState(localStorage.getItem('token'))
const setToken = t => {
doSetToken(t)
localStorage.setItem('token', token)
}
return (
<Context.Provider value={{ token, setToken }}>
{children}
</Context>
)
}
export { Context }
export default GlobalStateProvider
// src/App.js
import GlobalStateProvider from './providers/GlobalStateProvider'
// ...
const App = _props => {
return (
{/* Any component that is descendant of this one can access the context values, an will re-render if they change */}
<GlobalStateProvider>
{/* ... the rest of your components */}
</GlobalStateProvider>
)
}
// ...
// your particular component
import React, { useContext } from 'react'
import { Context } from 'path/to/GlobalStateProvider'
const SomeComponent = _props => {
// Component will re-render if token changes
// you can change token from wherever by using `setToken`
const { token, setToken } = useContext(Context)
if (token) {
// do this
} else {
// do that
}
}