Redux 工具包和 Axios
Redux Toolkit and 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);
})
}
}
});
axios 正在连接到 API,因为要打印到控制台的注释行正在向我显示数据。然而, state.products.concat(response.data.products);抛出以下错误:
类型错误:无法在已撤销的代理上执行'get'
有什么办法可以解决这个问题吗?
这是因为你的 reducer 函数不是纯函数,它不应该有任何异步调用。
像这样的东西应该有用。它将修复您遇到的错误
const products = createSlice({
name: "products",
initialState: {
products: []
},
reducers: {
reducer2: (state, { payload }) => {
return { products: [...state.products, ...payload]}
})
}
}
});
和api应该在
外调用
const fetchProducts = () => {
axios.get('myurl')
.then(response => {
//console.log(response.data.products);
store.dispatch(products.actions.reducer2(response.data.products))
})
};
PS: 运行以上代码没有试过,您可能需要根据自己的需要进行修改。
我更愿意将 createAsyncThunk
用于 API 具有 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;
在您的 store.js
中添加 productsSlice: productsSlice.reducer
in out store reducer。
然后为了在组件中使用添加这些代码...我也更喜欢使用 hook
import { useSelector, useDispatch } from "react-redux";
import {
fetchProducts,
selectProducts,
} from "path/productSlice.js";
然后最后一部分像这样在你的主管内部调用那些方法
const dispatch = useDispatch();
const { products } = useSelector(selectProducts);
React.useEffect(() => {
dispatch(fetchProducts());
}, [dispatch]);
最后,您可以在组件中以 products
的形式访问数据。
我正在使用 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);
})
}
}
});
axios 正在连接到 API,因为要打印到控制台的注释行正在向我显示数据。然而, state.products.concat(response.data.products);抛出以下错误:
类型错误:无法在已撤销的代理上执行'get'
有什么办法可以解决这个问题吗?
这是因为你的 reducer 函数不是纯函数,它不应该有任何异步调用。
像这样的东西应该有用。它将修复您遇到的错误
const products = createSlice({
name: "products",
initialState: {
products: []
},
reducers: {
reducer2: (state, { payload }) => {
return { products: [...state.products, ...payload]}
})
}
}
});
和api应该在
外调用const fetchProducts = () => {
axios.get('myurl')
.then(response => {
//console.log(response.data.products);
store.dispatch(products.actions.reducer2(response.data.products))
})
};
PS: 运行以上代码没有试过,您可能需要根据自己的需要进行修改。
我更愿意将 createAsyncThunk
用于 API 具有 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;
在您的 store.js
中添加 productsSlice: productsSlice.reducer
in out store reducer。
然后为了在组件中使用添加这些代码...我也更喜欢使用 hook
import { useSelector, useDispatch } from "react-redux";
import {
fetchProducts,
selectProducts,
} from "path/productSlice.js";
然后最后一部分像这样在你的主管内部调用那些方法
const dispatch = useDispatch();
const { products } = useSelector(selectProducts);
React.useEffect(() => {
dispatch(fetchProducts());
}, [dispatch]);
最后,您可以在组件中以 products
的形式访问数据。