有没有办法在 createSlice 中访问全局状态?
Is there a way to access global state in createSlice?
这是一个例子:
const user = createSlice({
name: 'user',
initialState: { name: '', age: 20 },
reducers: {
setUserName: (state, action) => {
state.name = action.payload // mutate the state all you want with immer
}
},
// "map object API"
extraReducers: {
[counter.actions.increment]: (state, action) => {
state.age += 1
}
}
})
我可以访问计数器状态吗?
假设我只想在计数器为 30 时增加年龄。否则,我需要在 useEffect
挂钩中更改计数并分派一些处理年龄增加的操作(?)。
换句话说,使用redux-toolkit
根据当前全局状态计算状态切片的最佳方法是什么?
the Redux FAQ entry on sharing state between reducers.
中对此进行了介绍
粘贴重点:
- If a reducer needs to know data from another slice of state, the state tree shape may need to be reorganized so that a single reducer is handling more of the data.
- You may need to write some custom functions for handling some of these actions. This may require replacing
combineReducers
with your own top-level reducer function. You can also use a utility such as reduce-reducers
to run combineReducers
to handle most actions, but also run a more specialized reducer for specific actions that cross state slices.
- Async action creators such as
redux-thunk
have access to the entire state through getState()
. An action creator can retrieve additional data from the state and put it in an action, so that each reducer has enough information to update its own state slice.
我认为您可以像下面这样使用 thunkAPI 和 extrareducers,假设您有一个包含当前用户对象的 auth 切片:
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import ordersService from "./ordersService";
const initialState = {
orders: [],
isError: false,
isSuccess: false,
isLoading: false,
message: "",
};
//get orders
export const getOrders = createAsyncThunk(
"orders/getOrders",
async (__, thunkAPI) => {
try {
const userId = thunkAPI.getState().auth.user.id
return await ordersService.getOrders(userId);
} catch (error) {
const message =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
return thunkAPI.rejectWithValue(message);
}
}
);
export const ordersSlice = createSlice({
name: "orders",
initialState,
reducers: {
reset: (state) => {
state.isError = false;
state.isSuccess = false;
state.isLoading = false;
state.message = "";
},
},
extraReducers: (builder) => {
builder
.addCase(getOrders.pending, (state) => {
state.isLoading = true;
})
.addCase(getOrders.fulfilled, (state, action) => {
state.isLoading = false;
state.isSuccess = true;
state.orders = action.payload;
})
.addCase(getOrders.rejected, (state, action) => {
state.isLoading = false;
state.isError = true;
state.message = action.payload;
state.orders = [];
});
},
});
export const { reset, setOrder } = ordersSlice.actions;
export default ordersSlice.reducer;
这是一个例子:
const user = createSlice({
name: 'user',
initialState: { name: '', age: 20 },
reducers: {
setUserName: (state, action) => {
state.name = action.payload // mutate the state all you want with immer
}
},
// "map object API"
extraReducers: {
[counter.actions.increment]: (state, action) => {
state.age += 1
}
}
})
我可以访问计数器状态吗?
假设我只想在计数器为 30 时增加年龄。否则,我需要在 useEffect
挂钩中更改计数并分派一些处理年龄增加的操作(?)。
换句话说,使用redux-toolkit
根据当前全局状态计算状态切片的最佳方法是什么?
the Redux FAQ entry on sharing state between reducers.
中对此进行了介绍粘贴重点:
- If a reducer needs to know data from another slice of state, the state tree shape may need to be reorganized so that a single reducer is handling more of the data.
- You may need to write some custom functions for handling some of these actions. This may require replacing
combineReducers
with your own top-level reducer function. You can also use a utility such asreduce-reducers
to runcombineReducers
to handle most actions, but also run a more specialized reducer for specific actions that cross state slices.- Async action creators such as
redux-thunk
have access to the entire state throughgetState()
. An action creator can retrieve additional data from the state and put it in an action, so that each reducer has enough information to update its own state slice.
我认为您可以像下面这样使用 thunkAPI 和 extrareducers,假设您有一个包含当前用户对象的 auth 切片:
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import ordersService from "./ordersService";
const initialState = {
orders: [],
isError: false,
isSuccess: false,
isLoading: false,
message: "",
};
//get orders
export const getOrders = createAsyncThunk(
"orders/getOrders",
async (__, thunkAPI) => {
try {
const userId = thunkAPI.getState().auth.user.id
return await ordersService.getOrders(userId);
} catch (error) {
const message =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
return thunkAPI.rejectWithValue(message);
}
}
);
export const ordersSlice = createSlice({
name: "orders",
initialState,
reducers: {
reset: (state) => {
state.isError = false;
state.isSuccess = false;
state.isLoading = false;
state.message = "";
},
},
extraReducers: (builder) => {
builder
.addCase(getOrders.pending, (state) => {
state.isLoading = true;
})
.addCase(getOrders.fulfilled, (state, action) => {
state.isLoading = false;
state.isSuccess = true;
state.orders = action.payload;
})
.addCase(getOrders.rejected, (state, action) => {
state.isLoading = false;
state.isError = true;
state.message = action.payload;
state.orders = [];
});
},
});
export const { reset, setOrder } = ordersSlice.actions;
export default ordersSlice.reducer;