Redux reducer:当数组没有对象数据时将对象添加到数组

时间:2021-04-04 06:11:40

标签: reactjs redux react-redux

我正在尝试将 AJAX 调用返回的数据对象存储到 Redux 的 reducer 状态数组。 我有一些条件来检查获取的数据是否已经存在于 reducer 中。

这是我的问题:

  1. 调用 AJAX 调用操作的组件,它是来自 mapDispatchToProps 的函数,会导致无限循环。
  2. 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;

1 个答案:

答案 0 :(得分:2)

问题 1

<块引用>

调用 AJAX 调用动作的组件,它是 mapDispatchToProps 中的一个函数,导致无限循环。

由于您在 componentWillReceiveProps 中使用的条件,您看到了无限 调用。

nextProps.products.fetched总是 true产品(数据)被获取之后。另请注意,每次 props 发生变化时都会调用 componentWillReceiveProps。这导致了无限次调用。

解决方案 1

如果您想在获取products 数据后调用fetchIsProductLiked,最好将旧的products 数据与新的数据进行比较 componentWillReceiveProps 中的一个如下:

componentWillReceiveProps(nextProps) {
  if (nextProps.products !== this.props.products) {
    nextProps.products.forEach((product) => {
      this.props.fetchIsProductLiked(product.id);
    });
  }
}

注意:您应该开始使用 componentDidUpdate,因为 componentWillReceiveProps 正在获得 deprecated


问题 2

<块引用>

reducer 中的 isProductLikedData 状态未正确更新。

没有更新,因为您使用了mapMap 返回一个相同长度的新数组(具有从回调返回的元素)(您希望添加一个新的元素).

解决方案 2

如果您只想在状态中不存在数据时才更新数据,您可以使用 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],
  };
}