我正试图将AJAX调用返回的数据对象存储到Redux的reducer状态数组中。我有一些条件来检查获取的数据是否已经存在于reducer内部。
以下是我的问题:
- 调用AJAX调用操作的组件,它是
mapDispatchToProps
中的一个函数,会导致无限循环 - 减速器中的
isProductLikedData
状态未正确更新
你能告诉我缺了什么吗?
这是我的代码:
isProductLikedActions.js-获取isProductLikend数据的操作。response.data
看起来像{status: 200, isProductLiked: boolean}
export function fetchIsProductLiked(productId) {
return function (dispatch) {
axios
.get(`/ajax/app/is_product_liked/${productId}`)
.then((response) => {
dispatch({
type: 'FETCH_IS_PRODUCT_LIKED_SUCCESS',
payload: { ...response.data, productId },
});
})
.catch((err) => {
dispatch({
type: 'FETCH_IS_PRODUCT_LIKED_REJECTED',
payload: err,
});
});
};
}
isProductLikedReducer.js-当array.length === 0
时,我将action.payload
对象添加到isProductLikedData
数组中。之后,我想检查isProductLikedData
中是否存在action.payload
对象,以防止重复。如果没有重复,我想做[...state.isProductLikedData, action.payload]
。
const initialState = {
isProductLikedData: [],
fetching: false,
fetched: false,
error: null,
};
export default function reducer(state = initialState, action) {
switch (action.type) {
case 'FETCH_IS_PRODUCT_LIKED': {
return { ...state, fetching: true };
}
case 'FETCH_IS_PRODUCT_LIKED_SUCCESS': {
return {
...state,
fetching: false,
fetched: true,
isProductLikedData:
state.isProductLikedData.length === 0
? [action.payload]
: state.isProductLikedData.map((data) => {
if (data.productId === action.payload.productId) return;
if (data.productId !== action.payload.productId)
return action.payload ;
}),
};
}
case 'FETCH_IS_PRODUCT_LIKED_REJECTED': {
return {
...state,
fetching: false,
error: action.payload,
};
}
}
return state;
}
Products.js-products
是在componentWillMount
中获取的一个数组。一旦nextProps.products.fetched
变为true,我想调用fetchIsProductLiked
来获取isProductLiked`数据。但这会导致一个无限循环。
class Products extends React.Component {
...
componentWillMount() {
this.props.fetchProducts();
}
...
componentWillReceiveProps(nextProps) {
if (nextProps.products.fetched) {
nextProps.products.map((product) => {
this.props.fetchIsProductLiked(product.id);
}
}
render() {
...
}
}
export default Products;
第1期
调用AJAX调用操作的组件,它是mapDispatchToProps中的一个函数,会导致无限循环。
由于您在componentWillReceiveProps
中使用的条件,您将看到无限调用。
在提取产品(数据(之后,nextProps.products.fetched
总是true
。此外,请注意,每次道具发生变化时都会调用componentWillReceiveProps
。这引起了无限的呼叫。
解决方案1
如果您想在提取产品数据后调用fetchIsProductLiked
,最好将旧的products
数据与componentWillReceiveProps
中的新数据进行比较,如下所示:
componentWillReceiveProps(nextProps) {
if (nextProps.products !== this.props.products) {
nextProps.products.forEach((product) => {
this.props.fetchIsProductLiked(product.id);
});
}
}
注意:您应该开始使用componentDidUpdate
,因为componentWillReceiveProps
正在被弃用。
第2期
reducer中的isProductLikedData状态未正确更新。这不是正在更新,因为您使用了map
。Map返回一个新数组(具有从回调返回的元素(,其长度与相同(但您希望添加一个新元素(。
解决方案2
如果只想在州中不存在数据时更新数据,可以使用某些数据来检查数据是否存在。并且,当返回false时,使用排列语法推送新数据:
case "FETCH_IS_PRODUCT_LIKED_SUCCESS": {
return {
...state,
fetching: false,
fetched: true,
isProductLikedData: state.isProductLikedData.some(
(d) => d.productId === action.payload.productId
)
? state.isProductLikedData
: [...state.isProductLikedData, action.payload],
};
}