【问题标题】:Using a callback while dispatching actions在调度操作时使用回调
【发布时间】:2018-05-06 23:30:32
【问题描述】:

我正在尝试对某些数据发出 GET 请求。 这是我的行动号召。

componentDidMount() {
     this.props.fetchData(() => {
         this.setState({ isLoading: false });
     });
}

在完成之前,我想暂时显示“正在加载...”,因为获取请求正在执行。我为此使用回调并设置我的本地状态。 这是我的带有“回调”的动作创建者。

export function fetchData(callback) {
    return (dispatch) => {
        axios.get(`/api/fetchsomething`)
            .then(() => callback())
            .catch((err) => {
                console.log(err.message);
            });
    }
}

这是上面相同的函数,但调度操作以便我可以接收作为道具并渲染到我的 ui。

export function fetchData(callback) {
    return (dispatch) => {
        axios.get(`/api/fetchsomething`)
            .then((response) => dispatch({ type: FETCH_DATA, payload: response }))
            .catch((err) => {
                console.log(err.message);
            });
    }
}

我的问题是如何在同一个动作创建函数中进行回调和调度动作?这甚至是一种好的做法吗?

【问题讨论】:

  • 如果你想要做的只是设置一个加载状态直到响应可用,你实际上可以在发出异步请求之前调度一个操作,在 redux 存储中设置加载状态,并在你清除它时清除它得到回应

标签: javascript reactjs redux axios redux-thunk


【解决方案1】:

你可以这样做

componentDidMount() {
  this.setState({ isLoading: true }, () => {
    // ensuring that you make the API request only 
    // after the local state `isLoading` is set to `true`
    this.props.fetchData().then(() => this.setState({ isLoading: false });
  });
}

并且,fetchData 将定义如下

export function fetchData(callback) {
  return (dispatch) => {
    return axios.get(`/api/fetchsomething`)
      .then((response) => dispatch({ type: FETCH_DATA, payload: response }))
      .catch((err) => console.log(err.message));
  }
}

如果您使用redux-thunk 中间件来使用异步操作,那么这些操作将返回Promises;这样您就可以在 Promise 解析后设置组件的本地状态。

【讨论】:

  • 感谢您的选择。
【解决方案2】:

在组件中:

.....
componentDidMount() {
    this.props.fetchData();
}
....

export default connect((state) => ({loading: state.loading, data: state.data}))(Component);

在行动中,你应该这样做:

....
export function fetchData() {
  return (dispatch) => {
    dispatch({ type: FETCHING_DATA});     //dispatch an action for loading state to set it to true

    return axios.get(`/api/fetchsomething`)
      .then((response) => dispatch({ type: DATA_FETCHED, payload: response }))
      .catch((err) => console.log(err.message));
  }
}
....

在reducer中,你应该这样做:

....
case 'FETCHING_DATA':
    return {
        ...state,
        loading: true,
    } 

case 'DATA_FETCHED':
    return {
        ...state,
        data: action.payload,
        loading: false,
    } 
    ....

我个人觉得你不应该在你的组件中放任何business logic,因为它可能会在你以后重构你的应用程序时引起一些问题。这意味着您的组件中不应有任何.then,并且所有内容都应通过 redux 进行引导(如果您的应用程序中有一些副作用)。因此,您应该从 redux 本身而不是在组件内部控制您的 loading 状态。

【讨论】:

  • 感谢您的选择。
猜你喜欢
  • 2017-11-02
  • 1970-01-01
  • 1970-01-01
  • 2016-04-20
  • 2019-09-28
  • 1970-01-01
  • 2021-07-21
  • 2020-11-24
  • 1970-01-01
相关资源
最近更新 更多