React useReducer清空initialState

问题描述

我正在尝试使用axios在initialState内部获取的数据,以便稍后可以在useReducer中使用它。但是,一旦我将其作为第二个参数的initialState传递,它就会返回一个没有对象的空数组。请帮助...:(

 const [prods,setProds] = useState([]);
  const getProds = () => {
    axios.get(`API`).then((res) => {
      const data = res.data;
      setProds(data.products);
    });
  };


  const result = prods.map(function (el) {
    const quantity = Object.assign({},el);
    quantity.count = 0;
    return quantity;
  });
  
  const initialState = {
    products: [result],};
  useEffect(() => {
    getProds();
  },[]);

console.log(initialState);

  const [countState,dispatch] = useReducer(counterReducer,initialState);

  console.log(countState);

一个和第二个日志的结果如下:

useReducer empties initialState

将计数加到每个后,API调用的结果看起来像这样:

enter image description here

这是我的减速器的代码,我检查了很多次,但看起来还不错:

export const counterReducer = (state,action) => {
  switch (action.type) {
    case "increment":
      return {
        ...state,products: state.products.map((product) =>
          product.id === action.id
            ? { ...product,count: product.count + 1 }
            : product
        ),};

    case "decrement":
      return {
        ...state,products: state.products.map((product) =>
          product.id === action.id
            ? {
                ...product,count: product.count !== 1 ? product.count - 1 : 1,}
            : product
        ),};
    default:
      return state;
  }
};

解决方法

useReducer仅在第一个渲染时(在axios完成之前)消耗initialState,在所有后续渲染中,它将仅从存储单元返回状态。 您要做的是在顶部致电useReducer

const [countState,dispatch] = useReducer(counterReducer,{products: []});

,然后在您的dispatch中呼叫getProds

const getProds = () => {
    axios.get(`API`).then((res) => {
      const data = res.data;
      setProds(data.products);
      dispatch({ type: "PRODUCTS_FETCHED",payload: data.products});
    });
  };

并根据需要在减速器中添加以设置状态。

export const counterReducer = (state,action) => {
  switch (action.type) {
    case "increment":
      return {
        ...state,products: state.products.map((product) =>
          product.id === action.id
            ? { ...product,count: product.count + 1 }
            : product
        ),};

    case "decrement":
      return {
        ...state,products: state.products.map((product) =>
          product.id === action.id
            ? {
                ...product,count: product.count !== 1 ? product.count - 1 : 1,}
            : product
        ),};
    case "PRODUCTS_FETCHED":
      return {
        ...state,products: action.payload
      };
    default:
      return state;
  }
};