在React Redux中重定向之前,如何等待操作完成?

时间:2019-11-25 20:13:37

标签: javascript reactjs redux promise async-await

我正在尝试根据Redux存储中的isLoggedin状态登录用户。我的登录组件从映射到道具的userLogin动作调度fetchLogin动作。

const Login = (props) => {
    const [userLogin, setUserLogin] = useState({ email: "", password: "" })

    const getValue = e => {
        e.preventDefault();
        setUserLogin({
            ...userLogin,
            [e.target.name]: e.target.value 
        });
    }

    const makeRequest = (e) => {
        e.preventDefault()
        props.userLogin(userLogin)

        if (props.isLoggedin === true) {
            console.log(Cookie.get('accessToken'))
            props.history.push('/dashboard')
        }
    }

    return (
        <Fragment>
            <Form onSubmit={makeRequest}>
                <Form.Group controlId="formBasicEmail">
                    <Form.Label>Email Address</Form.Label>
                    <Form.Control
                        type="email"
                        name="email"
                        placeholder="Enter email"
                        onChange={getValue}
                    >
                    </Form.Control>
                </Form.Group>
                <Form.Group controlId="formBasicPassword">
                    <Form.Label>Password</Form.Label>
                    <Form.Control
                        type="password"
                        name="password"
                        placeholder="Enter password"
                        onChange={getValue}
                    >
                    </Form.Control>

                </Form.Group>
                <Button
                    variant="primary"
                    type="submit"
                >
                    Login
            </Button>
            </Form>
        </Fragment>
    )
}

const mapStateToProps = (state) => ({
    isFetching: state.userReducer.isFetching,
    isLoggedin: state.userReducer.isLoggedin,
    isError: state.userReducer.isError,
    errMessage: state.userReducer.errMessage
});

const mapDispatchToProps = dispatch => ({
    userLogin: (userLogin) => {
        dispatch(fetchLogin(userLogin))
    }
});

export default connect(
    mapStateToProps,
    mapDispatchToProps
)(Login)


这里的问题是,当用户单击登录时,我执行的用于从后端登录用户的redux操作会花费一些时间,并且存储的更新速度不足以使userLogin函数确认用户是否已已登录。我知道这与Promise有关,但我不确定如何准确地做到这一点。

您可以在下面找到我的操作,唯一重要的操作是fetchLogin,这是从登录组件中分派的操作。

export const userLoginRequest = () => {
    return {
        type: USER_LOGIN_REQUEST,
        payload: {
            isFetching: true
        }
    };
}

export const userLoginSuccess = (user) => {
    return {
        type: USER_LOGIN_SUCCESS,
        payload: {
            user: {
                ...user
            },
            isLoggedin: true,
            isFetching: false
        }
    };
}

export const userLoginFailed = () => {
    return {
        type: USER_LOGIN_FAILED,
        payload: {
            isFetching: false,
            isError: true
        }
    };
}

export const fetchLogin = (userLogin) => dispatch => {
    dispatch(userLoginRequest())
    axios.post('/login', {
        email: userLogin.email,
        password: userLogin.password
    })
        .then(response => {
            if (response.status === 200) {
             dispatch(userLoginSuccess(response.data))
            }
        }, err => {
            console.log("Error", err)
         dispatch(userLoginFailed())
    })
}

1 个答案:

答案 0 :(得分:2)

您可以从操作中返回承诺,并在其解决后设置isLoggedin的状态:

export const fetchLogin = (userLogin) => dispatch => {
  dispatch(userLoginRequest())
  return axios.post('/login', {
      email: userLogin.email,
      password: userLogin.password
    })
    .then(response => {
      if (response.status === 200) {
        dispatch(userLoginSuccess(response.data))
      }
      return response; 
    }).catch(err => {
      console.log("Error", err)
      dispatch(userLoginFailed())
    })
}

// ...

 const makeRequest = (e) => {
   e.preventDefault()
   props.userLogin(userLogin).then(resp => {
     if (props.isLoggedin === true) {
       console.log(Cookie.get('accessToken'))
       props.history.push('/dashboard')
     }
   })
 }

为此,您还需要更新mapDispatchToProps才能真正返回调度:

const mapDispatchToProps = dispatch => ({
    userLogin: (userLogin) => dispatch(fetchLogin(userLogin))
});

另一件事,我只是意识到在这种情况下使用分派的Promise进行正确重定向实际上是不必要的,因为可以在isLoggedin中跟踪useEffect道具

 const makeRequest = (e) => {
  e.preventDefault()
  props.userLogin(userLogin)
}

useEffect(() => {
  if (props.isLoggedin === true) {
    console.log(Cookie.get('accessToken'))
    props.history.push('/dashboard')
  }
}, [props.isLoggedin])