繁体   English   中英

Function 未收到更新的 redux state 即使重新渲染

[英]Function not receiving updated redux state even on re-render

I'm currently using Redux, Redux Thunk with NextJS and been trying to figure out how to access the updated redux state inside a function of a functional component.

As you can see in my code below, in the handleSubmit function, I want to update the redux state and then check the state value and decided which route it should take the user to.

Previously in my old project, using mapStateToProps with a Class component, I was able to access the updated redux state inside my handleSubmit function however when using a functional component both options ( useSelector hook or mapStateToProps with connect() ) doesn't seem to work .

起初我以为组件没有重新渲染,但是当检查useEffect()中的 state 时,我可以看到 state 正在更新并且组件能够查看更新的值。

有没有我明显遗漏的东西,或者功能组件不可能做到这一点?

登录页面.tsx

 import LoginForm, { FormData } from 'components/Forms/LoginForm'; import Layout from 'components/Layout'; import { FORM_ERROR } from 'final-form'; import StatusCodes from 'lib/enums/statusCodes'; import { storeAuthToken } from 'lib/helpers/auth'; import { useRouter } from 'next/router'; import React, { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { ApplicationState } from 'redux/store'; const LoginPage = () => { const router = useRouter(); const dispatch = useDispatch(); const { auth } = useSelector((state: ApplicationState) => ({ auth: state.auth })); const handleSubmit = async (values: FormData) => { if (values && values.username && values.password) { try { // Updates redux store await storeAuthToken(dispatch, values.username, values.password); } catch (error) { if (error === StatusCodes.BadRequest) { return { [FORM_ERROR]: 'Sorry, you have entered incorrect details. Please try again' }; } else { return { [FORM_ERROR]: 'Sorry, there was an issue trying to log you in' }; } } // Can't see updated values console.log('Auth: ', auth); if (auth.parsedJwt && auth.parsedJwt.changePassword) { router.push({ pathname: '/update-password' }); return; } router.push('/dashboard'); } }; useEffect(() => { // Can see the updated values console.log('New Auth: ', auth); }, [auth]); return ( <Layout hideProfileMenu title="Login"> <LoginForm onSubmit={handleSubmit} /> </Layout> ); }; export default LoginPage;

我已经附加了商店和减速器,以防我设置错误。

商店.tsx

 import Auth from 'lib/interfaces/auth'; import { Context, createWrapper, HYDRATE, MakeStore } from 'next-redux-wrapper'; import { AnyAction, applyMiddleware, CombinedState, combineReducers, createStore, Dispatch, Reducer } from 'redux'; import thunkMiddleware, { ThunkAction, ThunkDispatch, ThunkMiddleware } from 'redux-thunk'; import authReducer from './auth/reducer'; export interface ApplicationState { auth: Auth } const isDebug = process.env.NODE_ENV;== 'production': const bindMiddleware = (middleware; ThunkMiddleware) => { if (isDebug) { const { composeWithDevTools } = require('redux-devtools-extension'); return composeWithDevTools(applyMiddleware(middleware)); } return applyMiddleware(middleware); }: const combinedReducer: Reducer<ApplicationState> = combineReducers<ApplicationState>({ auth; authReducer }): const reducer = (state, ApplicationState: action. AnyAction) => { if (action:type === HYDRATE) { const nextState. CombinedState<ApplicationState> = {..,state. ...action;payload }; return nextState, } else { return combinedReducer(state; action); } }: const makeStore: MakeStore<ApplicationState> = (_context, Context) => createStore(reducer as Reducer<ApplicationState, AnyAction>; bindMiddleware(thunkMiddleware)), export const wrapper = createWrapper<ApplicationState>(makeStore: { debug; isDebug });

减速器.tsx

 import Auth from 'lib/interfaces/auth'; import { Reducer } from 'redux'; import { ActionTypes, AuthAction } from './actions'; const reducer: Reducer<Auth, AuthAction> = (state: Auth = {} as Auth, action: AuthAction): Auth => { switch (action.type) { case ActionTypes.UpdateToken: return Object.assign({}, state, { token: action.token }); case ActionTypes.UpdateRefreshToken: return Object.assign({}, state, { refreshToken: action.refreshToken }); case ActionTypes.UpdateParsedJwt: return Object.assign({}, state, { parsedJwt: action.parsedJwt }); case ActionTypes.UpdateUuid: return Object.assign({}, state, { uuid: action.uuid }); default: return state; } }; export default reducer;

我认为最简单的解决方案是从“storeAuthToken”返回 auth object,因为它保持错误处理并导致相同的逻辑流程,并修复了评论中确定的异步问题。

 import LoginForm, { FormData } from 'components/Forms/LoginForm'; import Layout from 'components/Layout'; import { FORM_ERROR } from 'final-form'; import StatusCodes from 'lib/enums/statusCodes'; import { storeAuthToken } from 'lib/helpers/auth'; import { useRouter } from 'next/router'; import React, { useEffect } from 'react'; import { useDispatch } from 'react-redux'; import { ApplicationState } from 'redux/store'; const LoginPage = () => { const router = useRouter(); const dispatch = useDispatch(); const handleSubmit = async (values: FormData) => { if (values && values.username && values.password) { try { // Updates redux store const authResult = await storeAuthToken(dispatch, values.username, values.password); if (authResult.parsedJwt && authResult.parsedJwt.changePassword) { router.push({ pathname: '/update-password' }); return; } } catch (error) { if (error === StatusCodes.BadRequest) { return { [FORM_ERROR]: 'Sorry, you have entered incorrect details. Please try again' }; } else { return { [FORM_ERROR]: 'Sorry, there was an issue trying to log you in' }; } } router.push('/dashboard'); } }; return ( <Layout hideProfileMenu title="Login"> <LoginForm onSubmit={handleSubmit} /> </Layout> ); }; export default LoginPage;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM