【问题标题】:Redux reducer: Add object to array when the array doesn't have the object dataRedux reducer:当数组没有对象数据时将对象添加到数组
【发布时间】:2021-04-04 06:11:40
【问题描述】:

我正在尝试将 AJAX 调用返回的数据对象存储到 Redux 的减速器状态数组中。 我有一些条件来检查提取的数据是否已经存在于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 - 当array.length === 0 时,我将action.payload 对象添加到isProductLikedData 数组。之后,我想检查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;

【问题讨论】:

  • 你能显示你使用connect for Products组件连接到redux store的代码吗

标签: reactjs redux react-redux


【解决方案1】:

问题 1

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

由于您在 componentWillReceiveProps 中使用的条件,您看到 infinite 个调用。

在获取产品(数据)之后,

nextProps.products.fetched总是true。另外,请注意,每次道具发生变化时都会调用componentWillReceiveProps。这导致了无限调用。

解决方案 1

如果您想在 products 数据被获取后调用fetchIsProductLiked,最好将旧的products 数据与@987654331 中的新数据比较 @如下:

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],
  };
}

【讨论】:

  • 非常感谢 Ajeet。这就是我想做的。问题 1 已完美解决,但 .some 没有像我预期的那样更新状态:它返回布尔值而不是 state.isProductLikedData[...state.isProductLikedData, action.payload]
  • 正确。布尔值存储为 isProductLikedData 的值。我是这样写的:isProductLikedData: state.isProductLikedData.some((data) => data.productId === action.payload.productId ? state.isProductLikedData : [...state.isProductLikedData,.action.payload])
  • 哦,知道了。使用布尔值,.some 的返回,有条件地更新状态!这行得通!非常感谢!
猜你喜欢
  • 2017-07-12
  • 2019-10-02
  • 1970-01-01
  • 2018-08-22
  • 1970-01-01
  • 2022-01-13
  • 2018-09-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多