在我的简单 React 应用程序中,我通过多个子组件传递用户是否从父组件登录的状态,以便子组件可以登录与注销逻辑。SignIn
组件具有用于使用户登录的窗体,而Header
组件包含将用户注销的按钮。这一切都在起作用。
但是,我了解了 Redux,并希望实现它来清理我的状态。我从这个isLoggedIn状态开始。我也有redux工具包。
所以现在,我有一个看起来像这样的切片:
const initialState: AuthState = {
loggedIn: false,
authedUser: null,
}
export const authSlice = createSlice({
name: 'auth',
initialState,
reducers: {
login: (state) => {
state.loggedIn = true // Mutable change should be OK with redux-toolkit
},
logout: (state) => {
state.loggedIn = false
},
...
export const { login, logout, ... } = authSlice.actions
在Header
,我有:
...
let isLoggedIn = useSelector((state) => state.auth.loggedIn)
const dispatch = useDispatch()
...
const handleLogOut = e => {
console.log("Clicked log out");
localStorage.removeItem('token');
// setLoggedIn(false); <- this used to be a state passed down from the parent, pre-Redux
dispatch(logout());
navigate("/");
}
return (
...
<Button variant="contained" onClick={(e) => handleLogOut(e)}>
Log out
</Button>
...
)
当我单击该按钮时,当我在登录端实现了非常相似的代码并且在那里收到相同的错误Cannot update a component (Header) while rendering a different component (App).
我会收到错误。
我的假设是,该错误与在由按钮单击触发的函数中具有dispatch
有关,但我无法说出到底出了什么问题。
我尝试过的一件事是将dispatch
移动到useEffect
中。为此,我在组件的函数声明中创建了包含dispatch
的useEffect
,并让它在局部变量localIsLoggedIn
上触发,例如,该变量初始化为 true,然后单击函数设置为 false。这似乎也不起作用——useEffect
从未被解雇。
我在这里错过了什么?
它最终与dispatch()
调用的位置无关。问题是在我的 App.js 中,我有逻辑来检查本地存储中的身份验证令牌;如果找到令牌,则会有一个dispatch(login)
,如果没有,则会有一个dispatch(logout)
。我猜问题是当Header
发送自己的dispatch(logout)
时,当组件全部重新渲染时会引起一些冲突,从而导致该错误。
我所做的修复是从 App.js 中删除该身份验证检查,而是将其放入我的 authSlice.ts 文件中