Redux-toolkit - extraReducer 中出现类型错误的原因可能是什么?
Redux-toolkit - What could be the reason for a type-error in an extraReducer?
我的 redux-slice 出现以下错误:
Uncaught TypeError: Cannot read properties of undefined (reading 'type')
at Object.addCase (mapBuilders.ts:158:1)
at extraReducers (boerseSlice.js:89:1)
at executeReducerBuilderCallback (mapBuilders.ts:194:1)
at buildReducer (createSlice.ts:300:1)
at reducer (createSlice.ts:323:1)
at redux.js:436:1
at Array.forEach (<anonymous>)
at assertReducerShape (redux.js:434:1)
at combineReducers (redux.js:499:1)
at configureStore (configureStore.ts:144:1)
这是我切片的第 89 行:
.addCase(createBoersenwerte.fulfilled, (state,action)=>{
state.isLoading = false;
state.isSuccess = true;
state.boersenwerte.push(action.payload);
})
这是完整的切片:
import {createSlice, createAsyncThunk} from "@reduxjs/toolkit"
import boersenwerteService from "./boersenwerteService";
const initialState = {
boersenwerte: [],
isLoading:false,
isError:false,
isSuccess:false,
message:"",
}
export const createBoersenwerte = createAsyncThunk("boersenwerte/", async (boersenwerteData, thunkAPI)=>{
try{
const token = thunkAPI.getState().auth.user.token;
return await boersenwerteService.createBoersenwerte(boersenwerteData, token);
} catch(error){
const message = (error.response &&
error.response.data &&
error.response.data.message)
|| error.message
|| error.toString()
return thunkAPI.rejectWithValue(message);
}
})
//update
export const updateBoersenwerte = createAsyncThunk("/boersenwerte/update", async (id, thunkAPI)=>{
try{
const token = thunkAPI.getState().auth.user.token;
return await boersenwerteService.updateBoersenwerte(id, token);
} catch(error){
const message = (error.response
&& error.response.data
&& error.response.data.message)
|| error.message
|| error.toString();
return thunkAPI.rejectWithValue(message);
}
})
//delete
export const deleteBoersenwerte = createAsyncThunk("/boersenwerte/delete", async (id, thunkAPI)=>{
try{
const token = thunkAPI.getState().auth.user.token;
return await boersenwerteService.deleteBoersenwerte(id, token);
} catch(error){
const message = (error.response
&& error.response.data
&& error.response.data.message)
|| error.message
|| error.toString();
return thunkAPI.rejectWithValue(message);
}
})
//getOne
export const getBoersenwerte = createAsyncThunk("/boersenwerte/find/", async (id, thunkAPI)=>{
try{
return await boersenwerteService.getBoersenwerte(id);
} catch(error){
const message = (error.response
&& error.response.data
&& error.response.data.message)
|| error.message
|| error.toString();
return thunkAPI.rejectWithValue(message);
}
})
//getall
export const getAllBoersenwerte = createAsyncThunk("/boersenwerte/find", async (_, thunkAPI)=>{
try{
return await boersenwerteService.getAllBoersenwerte();
} catch(error){
const message = (error.response
&& error.response.data
&& error.response.data.message)
|| error.message
|| error.toString();
return thunkAPI.rejectWithValue(message);
}
})
export const boersenwerteSlice = createSlice({
name:"boersenwerte",
initialState,
reducers:{
reset: (state)=>initialState,
}, extraReducers: (builder)=>{
builder
.addCase(createBoersenwerte.pending, (state)=>{
state.isLoading = true;
})
.addCase(createBoersenwerte.fulfilled, (state,action)=>{
state.isLoading = false;
state.isSuccess = true;
state.boersenwerte.push(action.payload);
})
.addCase(createBoersenwerte.rejected, (state,action)=>{
state.isLoading = false;
state.isError = true;
state.message = action.payload;
})
.addCase(updateBoersenwerte.pending, (state)=>{
state.isLoading = true;
})
.addCase(updateBoersenwerte.fulfilled, (state, action)=>{
state.isLoading = false;
state.isSuccess = true;
state.boersenwerte.push(action.payload);
})
.addCase(updateBoersenwerte.rejected, (state, action)=>{
state.isLoading = false;
state.isError = true;
state.message = action.payload;
})
.addCase(deleteBoersenwerte.pending, (state)=>{
state.isLoading = true;
})
.addCase(deleteBoersenwerte.fulfilled, (state, action)=>{
state.isLoading = false;
state.isSuccess = true;
state.boersenwerte = state.boersenwerte.filter((boersenwerte)=> boersenwerte._id !== action.payload.id);
})
.addCase(deleteBoersenwerte.rejected, (state, action)=>{
state.isLoading = false;
state.isError = true;
state.message = action.payload;
})
.addCase(getBoersenwerte.pending, (state)=>{
state.isLoading = true;
})
.addCase(getBoersenwerte.fulfilled, (state, action)=>{
state.isLoading = false;
state.isSuccess = true;
state.boersenwerte = action.payload;
})
.addCase(getBoersenwerte.rejected, (state, action)=>{
state.isLoading = false;
state.isError = true;
state.message = action.payload;
})
.addCase(getAllBoersenwerte.pending, (state)=>{
state.isLoading = true;
})
.addCase(getAllBoersenwerte.fulfilled, (state, action)=>{
state.isLoading = false;
state.isSuccess = true;
state.boersenwerte = action.payload;
})
.addCase(getAllBoersenwerte.rejected, (state, action)=>{
state.isLoading = false;
state.isError = true;
state.message = action.payload;
})
}
})
export const {reset} = boersenwerteSlice.actions;
export default boersenwerteSlice.reducer;
这是完整的服务文件:
import axios from "axios";
const API_URL = "/api/boersenwerte/";
const createBoersenwerte = async (boersenwerteData, token)=>{
const config ={
headers:{
accessToken: token,
}
}
const response = await axios.post(API_URL, boersenwerteData, config);
return response.data;
}
//update
const updateBoersenwerte = async (boersenwerteId, boersenwerteData, token)=>{
const config = {
headers:{
accessToken: token,
}
}
const response = await axios.put(API_URL + boersenwerteId, boersenwerteData, config);
return response.data;
}
//delete
const deleteBoersenwerte = async (boersenwerteId, token)=>{
const config = {
headers:{
accessToken: token,
}
}
const response = await axios.delete(API_URL + boersenwerteId, config);
return response.data;
}
//getOne
const getBoersenwerte = async (boersenwerteId)=>{
const response = await axios.get(API_URL + boersenwerteId);
return response.data;
}
//getAll
const getAllBoersenwerte = async ()=>{
const response = await axios.get(API_URL);
return response.data;
}
const boersenwerteService = {
createBoersenwerte,
updateBoersenwerte,
deleteBoersenwerte,
getBoersenwerte,
getAllBoersenwerte,
}
export default boersenwerteService;
感谢您的帮助。
问题是您没有提供 createBoersenwerte
thunk 的动作名称,请尝试更改此名称:
// add create after the slash
export const createBoersenwerte = createAsyncThunk("boersenwerte/create", async (boersenwerteData, thunkAPI)=>{
try{
const token = thunkAPI.getState().auth.user.token;
return await boersenwerteService.createBoersenwerte(boersenwerteData, token);
} catch(error){
const message = (error.response &&
error.response.data &&
error.response.data.message)
|| error.message
|| error.toString()
return thunkAPI.rejectWithValue(message);
}
})
查看您的代码,我注意到您对两个 thunk 使用相同的操作名称,您必须更改它以避免进一步的错误:
// changed to findAll
export const getAllBoersenwerte = createAsyncThunk("/boersenwerte/findAll", async (_, thunkAPI)=>{
try{
return await boersenwerteService.getAllBoersenwerte();
} catch(error){
const message = (error.response
&& error.response.data
&& error.response.data.message)
|| error.message
|| error.toString();
return thunkAPI.rejectWithValue(message);
}
})
最后一件事,也许它不适合你的情况,但了解一些技巧总是好的,redux-toolkit 为 [=13] 提供了 匹配实用程序 =],您可以使用它来减少为多个 thunk 定义相同逻辑的 reducer 的重复,take a look here。
我的 redux-slice 出现以下错误:
Uncaught TypeError: Cannot read properties of undefined (reading 'type')
at Object.addCase (mapBuilders.ts:158:1)
at extraReducers (boerseSlice.js:89:1)
at executeReducerBuilderCallback (mapBuilders.ts:194:1)
at buildReducer (createSlice.ts:300:1)
at reducer (createSlice.ts:323:1)
at redux.js:436:1
at Array.forEach (<anonymous>)
at assertReducerShape (redux.js:434:1)
at combineReducers (redux.js:499:1)
at configureStore (configureStore.ts:144:1)
这是我切片的第 89 行:
.addCase(createBoersenwerte.fulfilled, (state,action)=>{
state.isLoading = false;
state.isSuccess = true;
state.boersenwerte.push(action.payload);
})
这是完整的切片:
import {createSlice, createAsyncThunk} from "@reduxjs/toolkit"
import boersenwerteService from "./boersenwerteService";
const initialState = {
boersenwerte: [],
isLoading:false,
isError:false,
isSuccess:false,
message:"",
}
export const createBoersenwerte = createAsyncThunk("boersenwerte/", async (boersenwerteData, thunkAPI)=>{
try{
const token = thunkAPI.getState().auth.user.token;
return await boersenwerteService.createBoersenwerte(boersenwerteData, token);
} catch(error){
const message = (error.response &&
error.response.data &&
error.response.data.message)
|| error.message
|| error.toString()
return thunkAPI.rejectWithValue(message);
}
})
//update
export const updateBoersenwerte = createAsyncThunk("/boersenwerte/update", async (id, thunkAPI)=>{
try{
const token = thunkAPI.getState().auth.user.token;
return await boersenwerteService.updateBoersenwerte(id, token);
} catch(error){
const message = (error.response
&& error.response.data
&& error.response.data.message)
|| error.message
|| error.toString();
return thunkAPI.rejectWithValue(message);
}
})
//delete
export const deleteBoersenwerte = createAsyncThunk("/boersenwerte/delete", async (id, thunkAPI)=>{
try{
const token = thunkAPI.getState().auth.user.token;
return await boersenwerteService.deleteBoersenwerte(id, token);
} catch(error){
const message = (error.response
&& error.response.data
&& error.response.data.message)
|| error.message
|| error.toString();
return thunkAPI.rejectWithValue(message);
}
})
//getOne
export const getBoersenwerte = createAsyncThunk("/boersenwerte/find/", async (id, thunkAPI)=>{
try{
return await boersenwerteService.getBoersenwerte(id);
} catch(error){
const message = (error.response
&& error.response.data
&& error.response.data.message)
|| error.message
|| error.toString();
return thunkAPI.rejectWithValue(message);
}
})
//getall
export const getAllBoersenwerte = createAsyncThunk("/boersenwerte/find", async (_, thunkAPI)=>{
try{
return await boersenwerteService.getAllBoersenwerte();
} catch(error){
const message = (error.response
&& error.response.data
&& error.response.data.message)
|| error.message
|| error.toString();
return thunkAPI.rejectWithValue(message);
}
})
export const boersenwerteSlice = createSlice({
name:"boersenwerte",
initialState,
reducers:{
reset: (state)=>initialState,
}, extraReducers: (builder)=>{
builder
.addCase(createBoersenwerte.pending, (state)=>{
state.isLoading = true;
})
.addCase(createBoersenwerte.fulfilled, (state,action)=>{
state.isLoading = false;
state.isSuccess = true;
state.boersenwerte.push(action.payload);
})
.addCase(createBoersenwerte.rejected, (state,action)=>{
state.isLoading = false;
state.isError = true;
state.message = action.payload;
})
.addCase(updateBoersenwerte.pending, (state)=>{
state.isLoading = true;
})
.addCase(updateBoersenwerte.fulfilled, (state, action)=>{
state.isLoading = false;
state.isSuccess = true;
state.boersenwerte.push(action.payload);
})
.addCase(updateBoersenwerte.rejected, (state, action)=>{
state.isLoading = false;
state.isError = true;
state.message = action.payload;
})
.addCase(deleteBoersenwerte.pending, (state)=>{
state.isLoading = true;
})
.addCase(deleteBoersenwerte.fulfilled, (state, action)=>{
state.isLoading = false;
state.isSuccess = true;
state.boersenwerte = state.boersenwerte.filter((boersenwerte)=> boersenwerte._id !== action.payload.id);
})
.addCase(deleteBoersenwerte.rejected, (state, action)=>{
state.isLoading = false;
state.isError = true;
state.message = action.payload;
})
.addCase(getBoersenwerte.pending, (state)=>{
state.isLoading = true;
})
.addCase(getBoersenwerte.fulfilled, (state, action)=>{
state.isLoading = false;
state.isSuccess = true;
state.boersenwerte = action.payload;
})
.addCase(getBoersenwerte.rejected, (state, action)=>{
state.isLoading = false;
state.isError = true;
state.message = action.payload;
})
.addCase(getAllBoersenwerte.pending, (state)=>{
state.isLoading = true;
})
.addCase(getAllBoersenwerte.fulfilled, (state, action)=>{
state.isLoading = false;
state.isSuccess = true;
state.boersenwerte = action.payload;
})
.addCase(getAllBoersenwerte.rejected, (state, action)=>{
state.isLoading = false;
state.isError = true;
state.message = action.payload;
})
}
})
export const {reset} = boersenwerteSlice.actions;
export default boersenwerteSlice.reducer;
这是完整的服务文件:
import axios from "axios";
const API_URL = "/api/boersenwerte/";
const createBoersenwerte = async (boersenwerteData, token)=>{
const config ={
headers:{
accessToken: token,
}
}
const response = await axios.post(API_URL, boersenwerteData, config);
return response.data;
}
//update
const updateBoersenwerte = async (boersenwerteId, boersenwerteData, token)=>{
const config = {
headers:{
accessToken: token,
}
}
const response = await axios.put(API_URL + boersenwerteId, boersenwerteData, config);
return response.data;
}
//delete
const deleteBoersenwerte = async (boersenwerteId, token)=>{
const config = {
headers:{
accessToken: token,
}
}
const response = await axios.delete(API_URL + boersenwerteId, config);
return response.data;
}
//getOne
const getBoersenwerte = async (boersenwerteId)=>{
const response = await axios.get(API_URL + boersenwerteId);
return response.data;
}
//getAll
const getAllBoersenwerte = async ()=>{
const response = await axios.get(API_URL);
return response.data;
}
const boersenwerteService = {
createBoersenwerte,
updateBoersenwerte,
deleteBoersenwerte,
getBoersenwerte,
getAllBoersenwerte,
}
export default boersenwerteService;
感谢您的帮助。
问题是您没有提供 createBoersenwerte
thunk 的动作名称,请尝试更改此名称:
// add create after the slash
export const createBoersenwerte = createAsyncThunk("boersenwerte/create", async (boersenwerteData, thunkAPI)=>{
try{
const token = thunkAPI.getState().auth.user.token;
return await boersenwerteService.createBoersenwerte(boersenwerteData, token);
} catch(error){
const message = (error.response &&
error.response.data &&
error.response.data.message)
|| error.message
|| error.toString()
return thunkAPI.rejectWithValue(message);
}
})
查看您的代码,我注意到您对两个 thunk 使用相同的操作名称,您必须更改它以避免进一步的错误:
// changed to findAll
export const getAllBoersenwerte = createAsyncThunk("/boersenwerte/findAll", async (_, thunkAPI)=>{
try{
return await boersenwerteService.getAllBoersenwerte();
} catch(error){
const message = (error.response
&& error.response.data
&& error.response.data.message)
|| error.message
|| error.toString();
return thunkAPI.rejectWithValue(message);
}
})
最后一件事,也许它不适合你的情况,但了解一些技巧总是好的,redux-toolkit 为 [=13] 提供了 匹配实用程序 =],您可以使用它来减少为多个 thunk 定义相同逻辑的 reducer 的重复,take a look here。