React Redux-等待异步api调用完成,然后分派下一个操作

时间:2020-06-03 08:23:42

标签: reactjs redux react-redux

我正在使用React + Redux的Web应用程序,后端使用Django(DRF)。我正在使用axios发送我的API请求,这是异步的。我现在面临的问题是,在分派下一个动作之前,分派的动作不会等待API调用完成。下面是我的代码

const mapDispatchToProps = dispatch => ({
    success: id => {
        dispatch(fetchSalesProject(id));
        dispatch(createMessage('Requirement successfully updated!'))
    }
})

fetchSalesProject操作(axiosInstance只是对axios调用的自定义修改,功能相同)

export const fetchSalesProject = (id) => (dispatch) => {
    console.log('enter sales project action')
    axiosInstance
        .get(`/sales-project/detail/${id}/`)
        .then((res) => {
            console.log('fetched data')
            dispatch({
                type: FETCH_SALES_PROJECT,
                payload: res.data,
            });
        })
        .catch((err) => dispatch(returnErrors(err.response.data, err.response.status)));
};

createMessage操作

export const createMessage = (message) => {
  console.log('message')
  return {
    type: CREATE_MESSAGE,
    message: message,
  };
};

在调用this.props.success(请参阅mapDispatchToProps)时,会在接收到api调用响应数据之前显示该消息(通过console.log('message')在console.log('fetched之前运行)这一事实可以看出数据”)

在运行createMessage操作之前,我希望从api调用中获取数据,是否有关于如何完成此操作的建议?我是React的新手,尤其是Redux,所以希望你们能为我指出正确的方向。

此外,我是否可以检查在mapDispatchToProps中进行分派以及在操作内进行分派是否错误(请参阅fetchSalesProject操作)。它会引起性能问题还是会皱眉呢?请告诉我,因为我对Redux感到很困惑。

感谢大家通读,感谢所有帮助:-)

2 个答案:

答案 0 :(得分:2)

从UI分发时,您只是向reducer发送一个对象,该对象将依次减少商店的状态,并在流程结束时重新呈现引用已更改道具的组件。在分派第一个动作的那一刻,没有任何东西告诉组件在将下一个对象发送给reducer之前应该等待的组件

所以您有2个选择,

第一个操作是在UI本身上,使用componentDidUpdateuseEffect可以在第一个操作减少后运行第二个操作


 componentDidUpdate(prevProps) {
       if (prevProps.salesProject != this.props.salesProject)
         dispatch(createMessage('Requirement successfully updated!'))
      }

而我假设dispatch(fetchSalesProject(id));修改了salesProject属性

另一种方法是,如果您实际上对messagesalesProject感到满意,可以将它们归还给reducer,那就是将它们分派到一个动作中


 export const fetchSalesProjectAndMessage = (id, message) => (dispatch) => {
  console.log('enter sales project action')
  axiosInstance
    .get(`/sales-project/detail/${id}/`)
    .then((res) => {
        console.log('fetched data')
        dispatch({
            type: FETCH_SALES_PROJECT_AND_MESSAGE,
            payload: { data: res.data, message }
        });
    })
    .catch((err) => dispatch(returnErrors(err.response.data, err.response.status)));
 };

在减速器payload.data上,payload.message都将引用所需的信息

答案 1 :(得分:2)

有一个更好的方法可以执行此操作,该方法不会强制您组合两个动作创建者。当重击动作创建者返回承诺时,您可以等待它。您当前的代码未返回axios承诺,但是如果您返回了它,则可以执行以下操作:\

const mapDispatchToProps = (dispatch) => ({
  success: (id) => {
    dispatch(fetchSalesProject(id)).then(() =>
      dispatch(//wait for fetchSalesProject to finish
        createMessage('Requirement successfully updated!')
      )
    );
  },
});

export const fetchSalesProject = (id) => (dispatch) => {
  console.log('enter sales project action');
  return axiosInstance //you did not return anything here
    .get(`/sales-project/detail/${id}/`)
    .then((res) => {
      console.log('fetched data');
      dispatch({
        type: FETCH_SALES_PROJECT,
        payload: res.data,
      });
    })
    .catch((err) => {
      dispatch(
        returnErrors(err.response.data, err.response.status)
      );
      //return rejected promise here
      return Promise.reject(err);
    });
};