【问题标题】:UseEffect not fired when redux props change caused by async api call with redux-thunk当使用 redux-thunk 的异步 api 调用导致 redux 道具更改时不会触发 UseEffect
【发布时间】:2020-02-18 17:57:56
【问题描述】:

我有一个与 redux 连接的功能登录页面,我正在触发一个异步事件 onSubmit,它将触发 emailLogin 操作,我正在使用 useEffect 来检测 isLoading 属性的变化以查看是否登录完成与否。如果登录成功,redux store 应该有用户对象,如果登录失败,用户应该保持为空。

问题是,我知道登录成功了,应该触发isLoading的变化,决定useEffect的参数,但是useEffect没有被触发。此外,await emailLogin(authData); 行之后的 console.log('done'); 永远不会被触发。有点不对劲。

import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import { Link, useHistory } from 'react-router-dom';
import { emailLogin } from '../actions/index';

function Login({ user, isLoading, emailLogin }) {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const history = useHistory();

  useEffect(() => {
    console.log('useEffect fired', user, isLoading); //<-----This does not fire after login success
    if (user) {
      history.push('/protected_home');
    } 
  }, [isLoading]);

  const submitEmailLoginForm = async (e) => {
    e.preventDefault();
    const authData = { email, password };
    await emailLogin(authData);
    console.log('done'); // <------- This is never fired
  };

  return (
    <div>
      <h2>Login</h2>
      <Link to="/">back</Link>
      <form onSubmit={submitEmailLoginForm}>
        <label>
          email:
          <input
            type="text"
            name="email"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
          />
        </label>
        <label>
          password:
          <input
            type="text"
            name="password"
            value={password}
            onChange={(e) => setPassword(e.target.value)}
          />
        </label>
        <input type="submit" value="Submit" />
      </form>
    </div>
  );
}

const mapStateToProps = (state) => ({
  user: state.user,
  isLoading: state.isLoading
});

const mapDispatch = {
  emailLogin: emailLogin
};

export default connect(mapStateToProps, mapDispatch)(Login);

我的动作文件:

import axios from 'axios';

export const authActions = {
  EMAIL_LOGIN_START: '@@EMAIL_LOGIN_START',
  EMAIL_LOGIN_SUCCESS: '@@EMAIL_LOGIN_SUCCESS'
};

export const emailLogin = ({ email, password }) => async (dispatch) => {
  dispatch({ type: authActions.EMAIL_LOGIN_START });
  try {
    const response = await axios.post('http://localhost:5001/api/auth', {
      email: email,
      password: password
    });
    dispatch({
      type: authActions.EMAIL_LOGIN_SUCCESS,
      payload: {
        user: { ...response.data }
      }
    });
  } catch (error) {
    console.log('Should dispatch api error', error.response);
  }
};

我的减速机:

import { authActions } from '../actions/index';

const initialState = {
  user: null,
  isLoading: false
};

const userReducer = (state = initialState, action) => {
  switch (action.type) {
    case authActions.EMAIL_LOGIN_START:
      return { ...state, isLoading: true };
    case authActions.EMAIL_LOGIN_SUCCESS:
      console.log('Reducer check => Login is success'); //<-----this line is printed
      return { ...state, user: action.payload.user, isLoading: false };
    default:
      return state;
  }
};

export default userReducer;

在reducer中,我看到成功动作实际上是通过检查console.log()触发的。同样在 redux 开发工具中,我实际上可以看到登录成功并且 isLoading 属性已更改:

【问题讨论】:

  • 不是导致您的问题的原因,但 useEffect 调用应该同时接收 [isLoading, user] 作为依赖项。
  • @elyalvarado 很好,但它甚至不适用于 isLoading,这显然已经改变了,所以我想首先关注这一点
  • 它改变了两次:false -&gt; true -&gt; false 也许它做得太快了,反应在渲染第一个改变时会有所反应。添加用户并告诉我它是否有效
  • 你在哪里使用用户reducer?
  • @TomMendelson 目前是我唯一的减速器

标签: reactjs redux react-redux redux-thunk


【解决方案1】:

这解决了我的问题

const mapStateToProps = (state) => ({
  user: state.userReducer.user,
  isLoading: state.userReducer.isLoading
});

【讨论】:

    猜你喜欢
    • 2020-10-28
    • 2019-11-12
    • 2018-01-31
    • 2017-10-23
    • 2019-12-17
    • 2021-12-11
    • 2021-05-05
    • 2018-07-19
    • 2017-02-04
    相关资源
    最近更新 更多