【问题标题】: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然后登录了,怎么办?

标签: javascript node.js reactjs redux async-await


【解决方案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(()=&gt;{},[isAuth]) React Hook has a missing dependency: 'history' 内的虚拟工作室代码中显示警告
  • PrivateRoute.js我也用isAuthredux state,它返回false,我是否也需要在PrivateRoute.js中使用useEffect
  • 我不知道我的PrivateRoute.js到底发出了什么,即使我从localStorage &amp; session中清除了Token,我仍然可以访问localhost:3001/dashboard,没有restriction完全没有
猜你喜欢
  • 2020-07-11
  • 2020-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-13
  • 2019-02-13
  • 1970-01-01
  • 2022-06-15
相关资源
最近更新 更多