我正在尝试将 AJAX 调用返回的数据对象存储到 Redux 的 reducer 状态数组。 我有一些条件来检查获取的数据是否已经存在于 reducer 中。
这是我的问题:
mapDispatchToProps
的函数,会导致无限循环。isProductLikedData
减速器中的状态未正确更新。你能说出我遗漏了什么吗?
这是我的代码:
isProductLikedActions.js - 获取 isProductLiked 数据的操作。 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 - 当 action.payload
时,我将 isProductLikedData
对象添加到 array.length === 0
数组。之后,我想检查 action.payload
中是否存在 isProductLikedData
对象以防止重复。如果没有重复,我想做[...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
变为真,我想调用 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;
答案 0 :(得分:2)
调用 AJAX 调用动作的组件,它是 mapDispatchToProps 中的一个函数,导致无限循环。
由于您在 componentWillReceiveProps
中使用的条件,您看到了无限 调用。
nextProps.products.fetched
是总是 true
在产品(数据)被获取之后。另请注意,每次 props 发生变化时都会调用 componentWillReceiveProps
。这导致了无限次调用。
如果您想在获取products 数据后调用fetchIsProductLiked
,最好将旧的products
数据与新的数据进行比较 componentWillReceiveProps
中的一个如下:
componentWillReceiveProps(nextProps) {
if (nextProps.products !== this.props.products) {
nextProps.products.forEach((product) => {
this.props.fetchIsProductLiked(product.id);
});
}
}
注意:您应该开始使用 componentDidUpdate
,因为 componentWillReceiveProps
正在获得 deprecated。
reducer 中的 isProductLikedData 状态未正确更新。
它没有更新,因为您使用了map
。 Map 返回一个相同长度的新数组(具有从回调返回的元素)(但您希望添加一个新的元素).
如果您只想在状态中不存在数据时才更新数据,您可以使用 some 来检查数据是否存在。并且,在返回 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],
};
}