使用 createSlice reduxtoolkit 进行重构
Refactoring with createSlice reduxtoolkit
我在使用 createSlice 进行重构时遇到问题,我是 redux-toolkit 的初学者并且已经查看了文档,但仍然 problems.if 有人可以为我指出正确的方向,这太棒了。这是工作代码
const SET_ALERT = 'setAlert';
const REMOVE_ALERT = 'alertRemoved';
export const setAlert =
(msg, alertType, timeout = 5000) =>
(dispatch) => {
const id = nanoid();
dispatch({
type: SET_ALERT,
payload: { msg, alertType, id },
});
setTimeout(() => dispatch({ type: REMOVE_ALERT, payload: id }), timeout);
};
const initialState = [];
export default function alertReducer(state = initialState, action) {
const { type, payload } = action;
switch (type) {
case SET_ALERT:
return [...state, payload];
case REMOVE_ALERT:
return state.filter((alert) => alert.id !== payload);
default:
return state;
}
}
您当前的 setAlert
动作创建者创建了一个 thunk 动作(一个以 dispatch
作为参数的动作),因此它不能是由 createSlice
自动生成的动作创建者。
创建切片
您可以使设置与现在的设置非常相似。您将有两个单独的操作来设置和删除警报,以及一个用于调度两者的 thunk。底层基本操作 可以 使用 createSlice
.
创建
import { createSlice, nanoid } from "@reduxjs/toolkit";
const slice = createSlice({
name: "alerts",
initialState: [],
reducers: {
addAlert: (state, action) => {
// modify the draft state and return nothing
state.push(action.payload);
},
removeAlert: (state, action) => {
// replace the entire slice state
return state.filter((alert) => alert.id !== action.payload);
}
}
});
const { addAlert, removeAlert } = slice.actions;
export default slice.reducer;
export const setAlert = (msg, alertType, timeout = 5000) =>
(dispatch) => {
const id = nanoid();
dispatch(addAlert({ msg, alertType, id }));
setTimeout(() => dispatch(removeAlert(id)), timeout);
};
createAsyncThunk
下一节完全没有必要,而且过于“棘手”。
如果我们考虑将警报打开为 'pending' 操作并将警报关闭为 'fulfilled' 操作,我们可以使用 createAsyncThunk
。它只有一个参数,因此您需要将 msg
、alertType
和 timeout
作为对象的属性传递。您可以使用 thunk 的唯一 ID,即 action.meta.requestId
而不是创建您自己的 ID。您还可以通过 action.meta.arg
.
访问操作的参数
如果需要,您仍然可以使用 createSlice
,但除非您有其他操作,否则与 createReducer
相比没有任何优势。您将使用 extraReducers
属性 而不是 reducers
.
来响应两个 thunk 操作
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
export const handleAlert = createAsyncThunk( "alert/set", (arg) => {
const { timeout = 5000 } = arg;
return new Promise((resolve) => {
setTimeout(() => resolve(), timeout);
});
});
export default createReducer(initialState, (builder) =>
builder
.addCase(handleAlert.pending, (state, action) => {
const { alertType, msg } = action.meta.arg;
const id = action.meta.requestId;
// modify the draft state and don't return anything
state.push({ alertType, msg, id });
})
.addCase(handleAlert.fulfilled, (state, action) => {
const id = action.meta.requestId;
// we are replacing the entire state, so we return the new value
return state.filter((alert) => alert.id !== id);
})
);
示例组件
import { handleAlert } from "../store/slice";
import { useSelector, useDispatch } from "../store";
export const App = () => {
const alerts = useSelector((state) => state.alerts);
const dispatch = useDispatch();
return (
<div>
{alerts.map((alert) => (
<div key={alert.id}>
<strong>{alert.alertType}</strong>
<span>{alert.msg}</span>
</div>
))}
<div>
<button
onClick={() =>
dispatch(
handleAlert({
alertType: "success",
msg: "action was completed successfully",
timeout: 2000
})
)
}
>
Success
</button>
<button
onClick={() =>
dispatch(
handleAlert({
alertType: "warning",
msg: "action not permitted"
})
)
}
>
Warning
</button>
</div>
</div>
);
};
export default App;
我在使用 createSlice 进行重构时遇到问题,我是 redux-toolkit 的初学者并且已经查看了文档,但仍然 problems.if 有人可以为我指出正确的方向,这太棒了。这是工作代码
const SET_ALERT = 'setAlert';
const REMOVE_ALERT = 'alertRemoved';
export const setAlert =
(msg, alertType, timeout = 5000) =>
(dispatch) => {
const id = nanoid();
dispatch({
type: SET_ALERT,
payload: { msg, alertType, id },
});
setTimeout(() => dispatch({ type: REMOVE_ALERT, payload: id }), timeout);
};
const initialState = [];
export default function alertReducer(state = initialState, action) {
const { type, payload } = action;
switch (type) {
case SET_ALERT:
return [...state, payload];
case REMOVE_ALERT:
return state.filter((alert) => alert.id !== payload);
default:
return state;
}
}
您当前的 setAlert
动作创建者创建了一个 thunk 动作(一个以 dispatch
作为参数的动作),因此它不能是由 createSlice
自动生成的动作创建者。
创建切片
您可以使设置与现在的设置非常相似。您将有两个单独的操作来设置和删除警报,以及一个用于调度两者的 thunk。底层基本操作 可以 使用 createSlice
.
import { createSlice, nanoid } from "@reduxjs/toolkit";
const slice = createSlice({
name: "alerts",
initialState: [],
reducers: {
addAlert: (state, action) => {
// modify the draft state and return nothing
state.push(action.payload);
},
removeAlert: (state, action) => {
// replace the entire slice state
return state.filter((alert) => alert.id !== action.payload);
}
}
});
const { addAlert, removeAlert } = slice.actions;
export default slice.reducer;
export const setAlert = (msg, alertType, timeout = 5000) =>
(dispatch) => {
const id = nanoid();
dispatch(addAlert({ msg, alertType, id }));
setTimeout(() => dispatch(removeAlert(id)), timeout);
};
createAsyncThunk
下一节完全没有必要,而且过于“棘手”。
如果我们考虑将警报打开为 'pending' 操作并将警报关闭为 'fulfilled' 操作,我们可以使用 createAsyncThunk
。它只有一个参数,因此您需要将 msg
、alertType
和 timeout
作为对象的属性传递。您可以使用 thunk 的唯一 ID,即 action.meta.requestId
而不是创建您自己的 ID。您还可以通过 action.meta.arg
.
如果需要,您仍然可以使用 createSlice
,但除非您有其他操作,否则与 createReducer
相比没有任何优势。您将使用 extraReducers
属性 而不是 reducers
.
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
export const handleAlert = createAsyncThunk( "alert/set", (arg) => {
const { timeout = 5000 } = arg;
return new Promise((resolve) => {
setTimeout(() => resolve(), timeout);
});
});
export default createReducer(initialState, (builder) =>
builder
.addCase(handleAlert.pending, (state, action) => {
const { alertType, msg } = action.meta.arg;
const id = action.meta.requestId;
// modify the draft state and don't return anything
state.push({ alertType, msg, id });
})
.addCase(handleAlert.fulfilled, (state, action) => {
const id = action.meta.requestId;
// we are replacing the entire state, so we return the new value
return state.filter((alert) => alert.id !== id);
})
);
示例组件
import { handleAlert } from "../store/slice";
import { useSelector, useDispatch } from "../store";
export const App = () => {
const alerts = useSelector((state) => state.alerts);
const dispatch = useDispatch();
return (
<div>
{alerts.map((alert) => (
<div key={alert.id}>
<strong>{alert.alertType}</strong>
<span>{alert.msg}</span>
</div>
))}
<div>
<button
onClick={() =>
dispatch(
handleAlert({
alertType: "success",
msg: "action was completed successfully",
timeout: 2000
})
)
}
>
Success
</button>
<button
onClick={() =>
dispatch(
handleAlert({
alertType: "warning",
msg: "action not permitted"
})
)
}
>
Warning
</button>
</div>
</div>
);
};
export default App;