我在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
。
我现在该怎么办?抱歉,这么长的帖子。
答案 0 :(得分:1)
实际上,我实际上希望getProductsAndPackagesActionCreator()
退还一个诺言,说实话,这很简单。我发现,如果您只是return
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 :(得分:0)
我认为您即将获得想要的东西。首先,您应该了解redux动作和诸如setState之类的反应动作是异步的,因此必须牢记这一点来应用逻辑。我将在某些方面解释我的想法:
您已在正确的位置 componentDidMount 处调用了操作创建者,也可以根据需要在任何onClick中调用此操作。
我猜想,一旦您调度动作,就将更改redux状态设置为true。因此,现在您可以在render函数中访问此属性,以便可以渲染Loader直到api调用完成。
当您的ajax函数完成时(无论是否出现错误),我想您是将loading设置为false并更新产品数据,以便现在就可以在仪表板中呈现已加载的产品。
您确定必须将空产品数组与接收到的数据进行比较吗?也许您可以签入渲染功能if (!this.props.products.length) return null
,当您加载页面时,您将看到一个加载器功能,随后将看到带有产品的仪表板。
如果您确实需要将以前的产品与收到的产品进行比较,请使用 componentDidUpdate 。在此方法中,您可以访问以前的道具并与实际道具进行比较,请谨慎比较数组,请记住[] === []为假。也许您可以比较长度,例如
componentDidUpdate(prevProps){
if(prevProps.products.length !=== this.props.products.lenth){
doSomething()
}
}
只是说componentDidUpdate是在渲染之后执行的,因此请谨慎使用代码,以免执行额外的渲染。
希望这会有所帮助,如果您不明白,请告诉我:)