为啥 redux 状态不能正确渲染?
Posted
技术标签:
【中文标题】为啥 redux 状态不能正确渲染?【英文标题】:Why redux state is not render correctly?为什么 redux 状态不能正确渲染? 【发布时间】:2021-08-06 15:07:48 【问题描述】:您好,我在用户正确登录后尝试将用户推送到仪表板时遇到了一个问题,但没有成功,下面是代码:
LoginForm.js
const isLoading, isAuth, error, message = useSelector(
(state) => state.login
);
const handleSubmit = (e) =>
e.preventDefault();
console.log(values);//values=email:'..', pass:'..'
if (formValidation())
dispatch(NewUserLogin(values));
console.log(isAuth); //print false but in redux state print true
if (isAuth) history.push('/dashboard');
;
LoginAction.js
export const NewUserLogin = (formValues) => async (dispatch) =>
try
dispatch(loginPending());
const status, message = await LoginAPIRequest(formValues);
if (status === 'success')
dispatch(loginSuccess(message));
else
dispatch(loginFailure(message));
console.log(status);
console.log(message);
catch (error)
dispatch(loginFailure(error.message));
;
loginSlice.js
import createSlice from '@reduxjs/toolkit';
const initialState =
isLoading: false,
isAuth: false,
error: '',
;
const loginSlice = createSlice(
name: 'Login',
initialState,
reducers:
loginPending: (state) =>
state.isLoading = true;
,
loginSuccess: (state, payload ) =>
state.isLoading = false;
state.isAuth = true;
state.message = payload;
state.error = '';
,
loginFailure: (state, payload ) =>
//actions.payload or shortcut payload
state.isLoading = false;
state.error = payload;
,
,
);
const reducer, actions = loginSlice;
export const loginPending, loginSuccess, loginFailure = actions;
export default reducer;
userAPI.js
import createEndpointsAPI, ENDPOINTS from './index';
export const LoginAPIRequest = (formValues) =>
return new Promise(async (resolve, reject) =>
//call api
try
await createEndpointsAPI(ENDPOINTS.LOGIN)
.create(formValues)
.then((res) =>
resolve(res.data);
if (res.data.status === 'success')
resolve(res.data);
sessionStorage.setItem('accessJWT', res.data.accessJWT);
localStorage.setItem('sms', JSON.stringify(res.data.refreshJWT));
console.log(res.data);
)
.catch((err) =>
reject(err);
);
catch (error)
console.log(error);
reject(error);
);
;
index.js(根 API)
import axios from 'axios';
export const ENDPOINTS =
LOGIN: 'user/login',
LOGOUT: 'user/logout',
REGISTER: 'user/register',
;
const baseURL = 'http://localhost:3040/v2/';
export const createEndpointsAPI = (endpoint) =>
let url = baseURL + endpoint + '/';
return
fetchAll: () => axios.get(url),
fetchById: (id) => axios.get(url + id),
create: (newData) => axios.post(url, newData),
update: (updateData, id) => axios.put(url + id, updateData),
delete: (id) => axios.delete(url + id),
;
;
App.js
<MuiThemeProvider theme=theme>
<CssBaseline />
<Router>
<Switch>
<Route path='/' exact>
<Login />
</Route>
<PrivateRoute path='/dashboard'>
<Dashboard />
</PrivateRoute>
<Route path='*' component=() => '404 NOT FOUND' />
</Switch>
</Router>
</MuiThemeProvider>
PrivateRoute.js
import useSelector from 'react-redux';
const PrivateRoute = ( component: Component, ...rest ) =>
const isAuth = useSelector((state) => state.login);
console.log(isAuth);
return (
<Route
...rest
render=(props) =>
isAuth ? (
<Component ...props />
) : (
<Redirect
to=
pathname: '/',
state: from: props.location ,
/>
);
/>
);
;
export default PrivateRoute;
问题是,isAuth 是一个 redux 状态,当用户正确登录时它应该返回 true,但它不是,我 console.log(isAuth) 第一次打印 false 即使用户正确登录,如果我再次单击登录,它在控制台日志中打印为 true 并将用户重定向到仪表板页面。 不知道为什么isAuth在使用正确登录的时候第一次返回false?请大家帮忙检查一下上面的代码,我都给你了。
【问题讨论】:
我console.log('Log In)
在NewUserLogin
函数中,实际上返回isAuth为false然后登录了,怎么办?
【参考方案1】:
日志:console.log(isAuth);
记录了stale closure,您可以尝试对 isAuth 施加影响,并在其为真时重定向。
这是一个例子:
const Component = (propps) =>
const isLoading, isAuth, error, message = useSelector(
(state) => state.login
);
const handleSubmit = (e) =>
//...dispatches but doesn't check isAuth
;
useEffect(() =>
//go to dashboard if isAuth is true
if (isAuth) history.push('/dashboard');
, [isAuth]);//run effect when isAuth changes
;
【讨论】:
你能给我举个例子来说明如何避免过时的关闭吗?如何在 isAuth 上渲染效果? @Jonh 添加示例 我通过使用useEffect
应用您的想法并添加依赖项[isAuth]
,它正在工作,但它在useEffect(()=>,[isAuth])
React Hook has a missing dependency: 'history'
内的虚拟工作室代码中显示警告
在PrivateRoute.js
我也用isAuth
从redux state
,它返回false
,我是否也需要在PrivateRoute.js
中使用useEffect
。
我不知道我的PrivateRoute.js
到底发出了什么,即使我从localStorage & session
中清除了Token
,我仍然可以访问localhost:3001/dashboard
,没有restriction
完全没有以上是关于为啥 redux 状态不能正确渲染?的主要内容,如果未能解决你的问题,请参考以下文章
ReactJS表单应用程序:如何阻止父组件重新渲染? /使用redux共享状态的正确方法
Redux 状态发生了变化,为啥不触发重新渲染? (Redux 传奇)