首页 文章

React Redux中的异步ActionCreator

提问于
浏览
9

我在React-Redux中很新 . 正在处理申请 . 问题是我遇到了Redux actionCreator异步执行的一些问题,可能是 .

以下是我的组件 . 说,我想从 componentDidMount() 或onclick事件监听器调用actionCreator .

class Dashboard extends PureComponent {

     componentDidMount() {

          this.props.getProductsAndPackages();

          let something = [];
          something = this.props.products;

     }
....................................
}

或者,函数 this.props.getProductsAndPackages(); 可以是一个onClick事件处理程序,它执行相同的操作,上下文是相同的 . 在我第一次解释我的代码后,我会问我的问题 .

在我的仪表板容器的下方:

Dashboard.propTypes = {
getProductsAndPackages: PropTypes.func.isRequired,
products: PropTypes.array.isRequired,
.......................

 };

const mapStateToProps = (state) => {
    return {
         .....................
         products: state.products.products,
         ...................
    };  
};


const mapDispatchToProps = (dispatch) => {
    return {
        getProductsAndPackages: () => dispatch(getProductsAndPackagesActionCreator()),
    };
};

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Dashboard));

我的actionCreator如下:

export const getProductsAndPackagesActionCreator = () => {

return (dispatch) => {

    dispatch(productsIsLoading(true));

    let url = 'xyz';

    if(!!localStorage.getItem('_token')) {
        const local_token = localStorage.getItem('_token');
        const fullToken = 'Bearer '.concat(local_token);

        axios.get(url, {headers: {Authorization: fullToken}})
            .then(response => {
                dispatch(productsIsLoading(false));
                if (response.data.statusCode === 200) {
                    dispatch(productsFetched(true));
                    dispatch(products(response.data.data));
                } else {
                    dispatch(productsFetched(false));
                    dispatch(productsErrors(response.data.message));
                }

            })
            .catch(error => {


            });

    } else {

        axios.get(url)
            .then(response => {
                dispatch(productsIsLoading(false));
                if (response.data.statusCode === 200) {
                    dispatch(productsFetched(true));
                    dispatch(products(response.data.data));
                } else {
                    dispatch(productsFetched(false));
                    dispatch(productsErrors(response.data.message));
                }

            })
            .catch(error => {
                console.log(error);
                dispatch(productsIsLoading(false));
                dispatch(productsErrors(error.message));

            });

    }


};
};

现在,我希望我的 getProductsAndPackagesActionCreator() 返回一个Promise或任何允许我的 something 变量获取从服务器返回的实际数据的东西 . 现在,当我获得实际数据时,行 something=this.props.products 已经执行,我回到了为 products 设置的initialValue .

我知道,每当我收到填充的 products 时,组件都会重新渲染,但这对我的决策没有帮助 .

顺便说一下,我正在使用 redux-thunk .

我现在应该怎么做 ?对不起这么长的帖子 .

2 回答

  • 0

    实际上,我想要 getProductsAndPackagesActionCreator() 返回一个承诺,说实话,这很简单 . 我想出如果你只是 axios.get()axios.post() ,它将返回一个承诺 . 因此,修改后的代码如下所示:

    export const getProductsAndPackagesActionCreator = () => {
    
      return (dispatch) => {
    
        dispatch(productsIsLoading(true));
    
        let url = 'xyz';
    
        if(!!localStorage.getItem('_token')) {
    
            return axios.get(url, {headers: {Authorization: fullToken}})
                .then(response => {
                   ............
                   ............
                })
                .catch(error => {
    
    
                });
    
        } else {
    
            return axios.get(url)
                .then(response => {
                    ...........
                    ...........
                })
                .catch(error => {
                    console.log(error);
                });
        }
      };
    };
    

    然后,我可以在 componentDidMount() 或任何onClick事件中执行类似下面的操作:

    this.props.getProductsAndPackages().then(() => {
        this.setState({
            ...this.state,
            clicked_product: this.props.product_by_id
        }, () => {
    
           //do other stuffs
    
        });
    });
    

    如果有任何问题,请随时告诉我 .

  • 1

    我认为你接近得到你想要的东西 . 首先,您应该了解redux操作和响应动作(如setState)是异步的,因此您必须应用逻辑来记住这一点 . 我将在某些方面解释我的想法:

    • 您已将动作创建者调用到正确的位置 componentDidMount ,如果需要,您也可以在任何onClick中调用此动作 .

    • 一旦你发出动作,你就会改变你的redux状态设置加载为true我想 . 所以现在你可以在渲染函数中访问这个属性,这样你就可以渲染一个Loader,直到你的api调用结束 .

    • 当您的ajax功能完成时,如果有错误,我认为您将加载设置为false并更新您的产品数据,因此您现在可以在仪表板中呈现已加载的产品 .

    您确定必须将空产品数组与收到的数据进行比较吗?也许您可以检查渲染功能 if (!this.props.products.length) return null ,当您加载页面时,您将看到一个加载器功能,稍后您将看到包含产品的仪表板 .

    如果您确实需要将以前的产品与收到的产品进行比较 componentDidUpdate 是您的方法 . 在这种方法中,你可以访问你以前的道具并与实际道具进行比较,小心比较数组,记住[] === []是假的 . 也许你可以比较长度,比如

    componentDidUpdate(prevProps){
       if(prevProps.products.length !=== this.props.products.lenth){          
           doSomething()
       }
    }
    

    只是说在渲染之后执行componentDidUpdate,所以要小心你的代码不要执行额外的渲染 .

    希望它有所帮助,如果你不明白任何只是告诉我:)

相关问题