Redux 工具包和 Axios

Jam*_*son 10 javascript toolkit reactjs redux axios

我正在使用 Redux Toolkit 通过 Axios 连接到 API。我正在使用以下代码:

const products = createSlice({
    name: "products",
    initialState: {
        products[]
    },
    reducers: {
        reducer2: state => {
            axios
                .get('myurl')
                .then(response => {
                    //console.log(response.data.products);
                    state.products.concat(response.data.products);
            })

        }
    }
});
Run Code Online (Sandbox Code Playgroud)

axios 正在连接到 API,因为打印到控制台的注释行向我显示了数据。但是, state.products.concat(response.data.products); 抛出以下错误:

类型错误:无法在已撤销的代理上执行“获取”

有没有办法解决这个问题?

SHU*_*USA 13

我更喜欢将createAsyncThunkAPI 数据用于extraReducers

假设这个页面名称是 productSlice.js

import { createSlice,createSelector,PayloadAction,createAsyncThunk,} from "@reduxjs/toolkit";

export const fetchProducts = createAsyncThunk(
  "products/fetchProducts", async (_, thunkAPI) => {
     try {
        //const response = await fetch(`url`); //where you want to fetch data
        //Your Axios code part.
        const response = await axios.get(`url`);//where you want to fetch data
        return await response.json();
      } catch (error) {
         return thunkAPI.rejectWithValue({ error: error.message });
      }
});

const productsSlice = createSlice({
   name: "products",
   initialState: {
      products: [],
      loading: "idle",
      error: "",
   },
   reducers: {},
   extraReducers: (builder) => {
      builder.addCase(fetchProducts.pending, (state) => {
        state. products = [];
          state.loading = "loading";
      });
      builder.addCase(
         fetchProducts.fulfilled, (state, { payload }) => {
            state. products = payload;
            state.loading = "loaded";
      });
      builder.addCase(
        fetchProducts.rejected,(state, action) => {
            state.loading = "error";
            state.error = action.error.message;
      });
   }
});


export const selectProducts = createSelector(
  (state) => ({
     products: state.products,
     loading: state.products.loading,
  }), (state) =>  state
);
export default productsSlice;
Run Code Online (Sandbox Code Playgroud)

在您的store.js添加productsSlice: productsSlice.reducer输出存储减速器中。

然后在组件中使用添加这些代码......我也更喜欢使用钩子

import { useSelector, useDispatch } from "react-redux";

import {
  fetchProducts,
  selectProducts,
} from "path/productSlice.js";
Run Code Online (Sandbox Code Playgroud)

然后最后一部分像这样在你的主管内部调用这些方法

const dispatch = useDispatch();
const { products } = useSelector(selectProducts);
React.useEffect(() => {
   dispatch(fetchProducts());
}, [dispatch]); 
Run Code Online (Sandbox Code Playgroud)

最后,您可以像products在组件中一样访问数据。

  • 我对这个答案表示赞赏,并强烈建议任何使用react-redux的人完整地阅读这个“redux Essentials”文档,并非常虔诚地遵循这些模式,它们太棒了!https://redux.js.org/tutorials/essentials/part-5-async-logic (2认同)

Kis*_*dev 8

这是因为您的 reducer 函数不是纯函数,它不应该有任何异步调用。

这样的事情应该工作。它将修复您遇到的错误

const products = createSlice({
    name: "products",
    initialState: {
        products: []
    },
    reducers: {
        reducer2: (state, { payload }) => {
                return { products: [...state.products, ...payload]}
         })

      }
    }
});
Run Code Online (Sandbox Code Playgroud)

和 api 应该在外面调用

const fetchProducts = () => {

   axios.get('myurl')
     .then(response => {
        //console.log(response.data.products);
        store.dispatch(products.actions.reducer2(response.data.products))
   })
};
Run Code Online (Sandbox Code Playgroud)

PS:没试过运行上面的代码,你可能需要根据你的需要进行修改。