redux-saga - Redux Saga:登录按钮的加载指示器
问题描述
我们使用以下 saga 通过电话注册用户:
function* signup() {
while (true) {
const {phone} = yield take("APP_SIGNUP");
nav.toCode();
const responseSignup = yield call(fetch.signUp, phone);
if (!responseSignup.success) {
yield put({type: "SIGNUP_SERVER_ERROR"});
continue;
}
let i;
for (i = 0; i < 3; i++) {
const {code} = yield take("APP_CHECK_CODE");
// MARKED LINE
const {success} = yield call(fetch.checkCode, {
phone,
code,
});
if (success) break;
yield put({ type: "APP_CHECK_CODE_WRONG" });
}
// code ok
if (i < 3) {
nav.toTabs();
yield put({ type: "APP_CHECK_USER" });
}
...
用户输入他的电话号码并显示一个屏幕,他在其中填写 4 位代码 - 你知道演习。
我们想添加一个加载指示器。有没有办法向调用 APP_CHECK_CODE 操作的人返回承诺*?
*在代码中标有“MARKED LINE”
解决方案
你可以从 thunk 中返回一个 Promise,但是如果你想坚持使用 saga,除了更改 redux 存储状态之外,没有简单的方法可以让调度操作的组件知道 saga 已完成。
所以我解决这个问题的方法是使用减速器,例如:
export (state = {checkingCode: false}, action) => {
switch (action.type) {
case APP_CHECK_CODE:
return {...state, checkingCode: true};
case APP_CHECK_CODE_WRONG:
case APP_CHECK_CODE_SUCCESS:
return {...state, checkingCode: false};
default:
return state;
}
}
然后根据checkingCode
值显示/隐藏加载指示器。
从理论上讲,如果您真的想将状态保留在组件本身中,您可以将诸如观察者之类的东西传递给 saga,然后等待它。
// component
const observable = Observable.create(observer => {
this.setState({loading: true});
dispatch({type: APP_CHECK_CODE, observer});
});
observable.subscribe({
complete: () => this.setState({loading: false}),
});
// saga
const {code, observer} = yield take("APP_CHECK_CODE")
...
observer.complete();
但老实说,这感觉很神奇,而且会导致比它的价值更多的麻烦。
推荐阅读
- c++ - 无法使用 g++ 用 C++ 代码编译 C 库
- jquery - 用数组中的对应元素替换元素
- javascript - 当外部源(firebase)更改单元格时,如何在谷歌表格中触发谷歌应用程序脚本?
- mongodb - 如何在 golang 中使用 $facet 和库 mgo?
- svg - 网络爬虫会在 SVG 中找到内容吗?
- virtualenv - 如何将包文件安装到 virtualenv 文件夹?
- multithreading - 在 cython 中有线程本地数组以便我可以调整它们的大小?
- swift - 苹果在 Swift 中的方式而不是覆盖?
- kong - 为什么Kong在请求时需要标头主机?
- android - Moshi 在浮点值上崩溃