【问题标题】:How to wait for action to complete before redirecting in react redux?如何在react redux中重定向之前等待操作完成?
【发布时间】:2019-11-25 20:13:37
【问题描述】:

我正在尝试根据 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 函数确认用户是登录。我知道这与承诺有关,但我不知道该怎么做。

您可以在下面找到我的操作,唯一重要的操作是 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())
    })
}

【问题讨论】:

    标签: javascript reactjs redux promise async-await


    【解决方案1】:

    您可以从您的操作中返回承诺并在解决后设置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))
    });
    

    还有一件事,我刚刚意识到在这种情况下使用 dispatch 的 promise 正确重定向实际上是没有必要的,因为可以跟踪 useEffect 中的 isLoggedin 属性

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

    【讨论】:

    • 我知道我需要返回一个承诺,但似乎我们实际上并没有返回一个承诺,我收到一个错误 .then is not a function。
    • return response; 应该不在状态,更新了答案。
    • 不,仍然无法正常工作,我仍然遇到同样的错误,但是检查定义了 useLogin 函数的 mapDispatchToProps,问题似乎是承诺没有直接返回给它。
    • 啊,对,你需要在那里使用隐式返回。更新了答案。
    • 你是MAAAN!是的,我认为这可能会更早地工作,但我很愚蠢,没有尝试它。谢谢!
    猜你喜欢
    • 2019-03-12
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    • 2021-10-10
    • 1970-01-01
    • 1970-01-01
    • 2014-07-14
    • 2019-12-29
    相关资源
    最近更新 更多