关于redux saga的导入方法
About the import method of redux saga
我是一名 2 个月的前端开发人员。
我是在进公司的同时学习React的,
所以有很多地方我不太了解
我目前正在分析代码以进行代码维护,
但是代码中有一个深奥的部分。
首先,在saga中,没有导入action函数的部分。 (即使在根传奇中。)
那么,是否可以在代码中隐式导入?
我附上了一些代码以帮助您理解。
rootSaga.js
import { all } from "redux-saga/effects";
import watcherLogin from "store/sagas/login";
import watcherSignUp from "store/sagas/signup";
export default function* rootSaga() {
yield all([
watcherLogin(),
watcherSignUp(),
]);
}
watcherLogin() > index.js
export { default } from "./watcherLoginSaga"
watcherLogin() > watcherLoginSaga.js
import { all, put, fork, takeLatest } from "redux-saga/effects";
import Cookies from "universal-cookie";
import { fetchData } from "store/sagas/baseSaga";
function* onRequestLogin(action) {
const payload = action.payload;
const { history } = payload;
const successAction = (res) => {
const cookies = new Cookies();
cookies.set("hdmKey", res.data, {
path: "/",
maxAge: 3600,
});
return function* () {
const payload = res;
yield put({
type: "login/GET_USERINFO_REQUEST",
payload: {
method: "get",
api: "getUserInfo",
// token: res.data.key,
history,
},
});
yield put({
type: "login/LOGIN_REQUEST_SUCCESS",
payload,
});
yield put({
type: "base/IS_LOGGED",
payload,
});
yield history.push("/");
};
};
const failureAction = (res) => {
return function* () {
yield put({
type: "base/SHOW_MODAL",
payload: {
dark: true,
modalName: "alert",
modalContent: "login failure",
modalStyle: "purpleGradientStyle",
modalTitle: "Wait!",
},
});
};
};
yield fork(fetchData, payload, successAction, failureAction);
}
...
export default function* watcherLoginSaga() {
yield all([
takeLatest("login/LOGIN_REQUEST", onRequestLogin),
]);
}
登录模块 > index.js
export { default } from "./loginModule";
登录模块 > loginModule.js
import createReducer from "store/createReducer";
import { changeStateDeep } from "lib/commonFunction";
export const types = {
LOGIN_REQUEST: "login/LOGIN_REQUEST",
LOGIN_REQUEST_SUCCESS: "login/LOGIN_REQUEST_SUCCESS",
...
};
export const actions = {
loginRequest: (payload) => ({
type: types.LOGIN_REQUEST,
payload,
}),
...
};
const INITIAL_STATE = {
data: {
isLogged: false,
...
},
};
const reducer = createReducer(INITIAL_STATE, {
[types.ON_LOGIN]: (state, action) => {
state.data.isLogged = true;
},
[types.LOGIN_REQUEST_SUCCESS]: (state, action) => {
state.data.isLogged = true;
state.data.key = action.payload?.key || "key";
},
...
});
export default reducer;
如果您能提供一点帮助,我将不胜感激。
action 只是一个带有 属性 type
的普通 javascript 对象。作为约定(但不是严格要求),操作对象将其数据存储在可选的 属性 payload
.
中
actionCreator 是一个接受 0 到多个参数并使用它们创建动作对象的函数。
您在发布的代码中看到的内容有效,但并不理想。我猜测对 loginModule.js
文件进行了某些改进,但这些改进并未带到 watcherLoginSaga.js
文件中。
您的 types
对象允许您使用变量 types.LOGIN_REQUEST
而不是原始字符串 "login/LOGIN_REQUEST"
。这有很多好处:
- 您的 IDE 获得了自动完成等智能感知支持
- 不用担心打错字
- 你可以改变底层raw的值
string
,你只需要改变一个地方
最后一个很关键,因为如果您现在将 types.LOGIN_REQUEST
的值更改为 "login/LOGIN_REQUEST"
以外的任何值,您的 sagas 将停止工作,因为它们使用的是原始字符串。所以你认为 saga 应该 从动作中导入是绝对正确的。我建议您导入 types
并用相应的变量替换字符串。
传奇通过 put
调度的操作也发生了同样的情况。
这段代码中发生的事情是 saga 从 type
和 payload
创建一个原始动作对象本身,而不是通过动作创建者函数创建它。 很好,但不是很好。与类型一样,动作创建者是一个抽象级别,可以更好地维护代码。如果 action creator 函数尚不存在,您绝对可以将 saga 中的逻辑提取出来。
例如,您的基本模块可以包括:
const types = {
IS_LOGGED: "base/IS_LOGGED",
SHOW_MODAL: "base/SHOW_MODAL"
};
export const actions = {
isLogged: (payload) => ({
type: types.IS_LOGGED,
payload
}),
showLoginFailure: () => ({
type: types.SHOW_MODAL,
payload: {
dark: true,
modalName: "alert",
modalContent: "login failure",
modalStyle: "purpleGradientStyle",
modalTitle: "Wait!"
}
})
};
并且您可以将创建操作的逻辑从您的 saga 中移开。
import { all, put, fork, takeLatest } from "redux-saga/effects";
import Cookies from "universal-cookie";
import { fetchData } from "store/sagas/baseSaga";
import {actions as loginActions, types as loginTypes} from "../some_path/loginModule";
import {actions as baseActions} from "../some_path/baseModule";
function* onRequestLogin(action) {
const payload = action.payload;
const { history } = payload;
const successAction = (res) => {
const cookies = new Cookies();
cookies.set("hdmKey", res.data, {
path: "/",
maxAge: 3600,
});
return function* () {
const payload = res;
yield put(loginActions.getUserInfoSuccess(history));
yield put(loginActions.loginSuccess(payload));
yield put(baseActions.isLogged(payload));
yield history.push("/");
};
};
const failureAction = (res) => {
return function* () {
yield put(baseActions.showLoginFailure());
};
};
yield fork(fetchData, payload, successAction, failureAction);
}
export default function* watcherLoginSaga() {
yield all([
takeLatest(loginTypes.LOGIN_REQUEST, onRequestLogin),
]);
}
我是一名 2 个月的前端开发人员。
我是在进公司的同时学习React的, 所以有很多地方我不太了解
我目前正在分析代码以进行代码维护, 但是代码中有一个深奥的部分。
首先,在saga中,没有导入action函数的部分。 (即使在根传奇中。)
那么,是否可以在代码中隐式导入?
我附上了一些代码以帮助您理解。
rootSaga.js
import { all } from "redux-saga/effects";
import watcherLogin from "store/sagas/login";
import watcherSignUp from "store/sagas/signup";
export default function* rootSaga() {
yield all([
watcherLogin(),
watcherSignUp(),
]);
}
watcherLogin() > index.js
export { default } from "./watcherLoginSaga"
watcherLogin() > watcherLoginSaga.js
import { all, put, fork, takeLatest } from "redux-saga/effects";
import Cookies from "universal-cookie";
import { fetchData } from "store/sagas/baseSaga";
function* onRequestLogin(action) {
const payload = action.payload;
const { history } = payload;
const successAction = (res) => {
const cookies = new Cookies();
cookies.set("hdmKey", res.data, {
path: "/",
maxAge: 3600,
});
return function* () {
const payload = res;
yield put({
type: "login/GET_USERINFO_REQUEST",
payload: {
method: "get",
api: "getUserInfo",
// token: res.data.key,
history,
},
});
yield put({
type: "login/LOGIN_REQUEST_SUCCESS",
payload,
});
yield put({
type: "base/IS_LOGGED",
payload,
});
yield history.push("/");
};
};
const failureAction = (res) => {
return function* () {
yield put({
type: "base/SHOW_MODAL",
payload: {
dark: true,
modalName: "alert",
modalContent: "login failure",
modalStyle: "purpleGradientStyle",
modalTitle: "Wait!",
},
});
};
};
yield fork(fetchData, payload, successAction, failureAction);
}
...
export default function* watcherLoginSaga() {
yield all([
takeLatest("login/LOGIN_REQUEST", onRequestLogin),
]);
}
登录模块 > index.js
export { default } from "./loginModule";
登录模块 > loginModule.js
import createReducer from "store/createReducer";
import { changeStateDeep } from "lib/commonFunction";
export const types = {
LOGIN_REQUEST: "login/LOGIN_REQUEST",
LOGIN_REQUEST_SUCCESS: "login/LOGIN_REQUEST_SUCCESS",
...
};
export const actions = {
loginRequest: (payload) => ({
type: types.LOGIN_REQUEST,
payload,
}),
...
};
const INITIAL_STATE = {
data: {
isLogged: false,
...
},
};
const reducer = createReducer(INITIAL_STATE, {
[types.ON_LOGIN]: (state, action) => {
state.data.isLogged = true;
},
[types.LOGIN_REQUEST_SUCCESS]: (state, action) => {
state.data.isLogged = true;
state.data.key = action.payload?.key || "key";
},
...
});
export default reducer;
如果您能提供一点帮助,我将不胜感激。
action 只是一个带有 属性 type
的普通 javascript 对象。作为约定(但不是严格要求),操作对象将其数据存储在可选的 属性 payload
.
actionCreator 是一个接受 0 到多个参数并使用它们创建动作对象的函数。
您在发布的代码中看到的内容有效,但并不理想。我猜测对 loginModule.js
文件进行了某些改进,但这些改进并未带到 watcherLoginSaga.js
文件中。
您的 types
对象允许您使用变量 types.LOGIN_REQUEST
而不是原始字符串 "login/LOGIN_REQUEST"
。这有很多好处:
- 您的 IDE 获得了自动完成等智能感知支持
- 不用担心打错字
- 你可以改变底层raw的值
string
,你只需要改变一个地方
最后一个很关键,因为如果您现在将 types.LOGIN_REQUEST
的值更改为 "login/LOGIN_REQUEST"
以外的任何值,您的 sagas 将停止工作,因为它们使用的是原始字符串。所以你认为 saga 应该 从动作中导入是绝对正确的。我建议您导入 types
并用相应的变量替换字符串。
传奇通过 put
调度的操作也发生了同样的情况。
这段代码中发生的事情是 saga 从 type
和 payload
创建一个原始动作对象本身,而不是通过动作创建者函数创建它。 很好,但不是很好。与类型一样,动作创建者是一个抽象级别,可以更好地维护代码。如果 action creator 函数尚不存在,您绝对可以将 saga 中的逻辑提取出来。
例如,您的基本模块可以包括:
const types = {
IS_LOGGED: "base/IS_LOGGED",
SHOW_MODAL: "base/SHOW_MODAL"
};
export const actions = {
isLogged: (payload) => ({
type: types.IS_LOGGED,
payload
}),
showLoginFailure: () => ({
type: types.SHOW_MODAL,
payload: {
dark: true,
modalName: "alert",
modalContent: "login failure",
modalStyle: "purpleGradientStyle",
modalTitle: "Wait!"
}
})
};
并且您可以将创建操作的逻辑从您的 saga 中移开。
import { all, put, fork, takeLatest } from "redux-saga/effects";
import Cookies from "universal-cookie";
import { fetchData } from "store/sagas/baseSaga";
import {actions as loginActions, types as loginTypes} from "../some_path/loginModule";
import {actions as baseActions} from "../some_path/baseModule";
function* onRequestLogin(action) {
const payload = action.payload;
const { history } = payload;
const successAction = (res) => {
const cookies = new Cookies();
cookies.set("hdmKey", res.data, {
path: "/",
maxAge: 3600,
});
return function* () {
const payload = res;
yield put(loginActions.getUserInfoSuccess(history));
yield put(loginActions.loginSuccess(payload));
yield put(baseActions.isLogged(payload));
yield history.push("/");
};
};
const failureAction = (res) => {
return function* () {
yield put(baseActions.showLoginFailure());
};
};
yield fork(fetchData, payload, successAction, failureAction);
}
export default function* watcherLoginSaga() {
yield all([
takeLatest(loginTypes.LOGIN_REQUEST, onRequestLogin),
]);
}