React Redux中的异步ActionCreator

Pla*_*tta 9 javascript reactjs redux redux-thunk react-redux

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

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

class Dashboard extends PureComponent {

     componentDidMount() {

          this.props.getProductsAndPackages();

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

     }
....................................
}
Run Code Online (Sandbox Code Playgroud)

或者,该函数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));
Run Code Online (Sandbox Code Playgroud)

我的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));

            });

    }


};
};
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

Sam*_*ano 0

我认为你已经接近得到你想要的了。首先,您应该了解 redux 操作和像 setState 这样的 React 操作是异步的,因此您必须在应用逻辑时牢记这一点。我将在某些方面解释我的想法:

  1. 您已在正确的位置调用了操作创建者componentDidMount,如果需要,您也可以在任何 onClick 中调用此操作。

  2. 我想,一旦你调度了这个动作,你就会改变你的 redux 状态设置,loading true 。现在您可以在渲染函数中访问此属性,这样您就可以渲染 Loader 直到 api 调用完成。

  3. 当您的 ajax 函数完成时,无论是否有错误,我想您正在将加载设置为 false 并更新您的产品数据,以便您现在可以在仪表板中呈现加载的产品。

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

如果您确实需要将以前的产品与收到的产品进行比较,则可以使用componentDidUpdate方法。在这个方法中,你可以访问之前的 props 并与实际的 props 进行比较,比较数组时要小心,记住 [] === [] 是 false。也许你可以比较长度,比如

componentDidUpdate(prevProps){
   if(prevProps.products.length !=== this.props.products.lenth){          
       doSomething()
   }
}
Run Code Online (Sandbox Code Playgroud)

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

希望对您有帮助,如果您有任何不明白的地方,请告诉我:)