使用 redux observable 显示警告框
Show alert box using redux observable
我在我的 React Native 应用程序中使用 redux observable,如果凭据无效,我想在我的登录屏幕上显示一个 React Native 警报对话框。我可以在我的史诗中触发警报但在史诗中我只能 return 一个可观察的,那么如何使用 redux 可观察的来实现这个?
- 更新 01
验证码:
export const signInFailure = (payload) => {
return {
type: SIGN_IN_FAILURE,
payload
}
};
const signInSuccessActions = (payload) => {
return Observable.concat(
Observable.of({type: SIGN_IN_SUCCESS, payload}),
Observable.of({type: 'Navigation/NAVIGATE', routeName: 'MainTabView'})
);
};
export const signInRequestEpic = action$ =>
action$.ofType(SIGN_IN_REQUEST)
.mergeMap(action => AuthService.login(action.email, action.password)
.flatMap(payload => payload.status === 200 ? signInSuccessActions(payload) : signInFailure(payload))
.catch(error => Observable.of({
type: SIGN_IN_FAILURE,
error
}))
);
在 React Native 中使用警报 api 只是 1 行
import {Alert} from "react-native";
Alert.alert(
'Invalid',
'Email or password incorrect',
)
更好的方法是在减速器中为 SIGN_IN_FAILURE 设置一个状态以及原因。在登录屏幕中使用这些并在 componentWillReceiveProps 中显示警报或在 render 方法中显示自定义模式错误消息
像这样
class LoginScreen{
componentWillMount(){
this.componentWillReceiveProps(this.props);
}
componentWillReceiveProps(nextProps){
const { loginError } = nextProps.loginState;
if(loginError){
Alert.alert('Invalid','Email or password incorrect')
}
}
render() {
const { loginError } = this.props.loginState
<View>
<Modal visible={loginError}>
</Modal>
</View>
}
}
const mapStateToProps = (state) => {
return {
loginState: state.login,
};
};
LoginScreen = connect(mapStateToProps)(LoginScreen);
export default LoginScreen;
确保在警报对话框关闭后重置 loginError redux 状态
旁注:大多数问题实际上只是普通的 RxJS questions in disguise,并不特定于 redux-observable;这几乎将所有内容都推迟到常规 RxJS。如果您能够将问题概括为普通的 RxJS,而无需 redux-observable 术语,找到答案通常会更容易,因为有大量的 RxJS 资源以及 Whosebug、Gitter 等用户可以提供帮助。
有几种方法可以做到。
在您现有的 Epic 中执行此操作
您可以使用 .do()
operator 产生不以任何方式影响操作流的副作用——比如只显示一个警告框而不进行任何确认。
export const signInRequestEpic = action$ =>
action$.ofType(SIGN_IN_REQUEST)
.mergeMap(action =>
AuthService.login(action.email, action.password)
.flatMap(payload => payload.status === 200
? signInSuccessActions(payload)
: signInFailure(payload)
)
.do({
error: ({ payload }) =>
Alert.alert('Invalid', `Sign in failed: ${payload.message}`)
})
.catch(error => Observable.of({
type: SIGN_IN_FAILURE,
error
}))
);
您也可以在 return SIGN_IN_FAILURE
的流之前在 .catch()
中执行此操作,但我个人喜欢将副作用分开,使它们更加突出。但这是:
.catch(error => {
Alert.alert('Invalid', `Sign in failed: ${error.message}`);
return Observable.of({
type: SIGN_IN_FAILURE,
error
});
})
在新史诗
中完成
如果您希望从 signInRequestEpic
中抽象出这种副作用,您可以创建另一个只监听失败的史诗,并使用 .do()
显示警报,然后使用 .ignoreElements()
运算符忽略匹配的动作,因为这个史诗不需要发出任何东西。
export const signInFailureEpic = action$ =>
action$.ofType(SIGN_IN_FAILURE)
.do(({ payload }) =>
Alert.alert('Invalid', `Sign in failed: ${payload.message}`)
)
.ignoreElements();
你应该使用哪一个?这取决于。如果您希望在 之前 更新您的 redux 商店,则显示警报,那么您肯定会想要使用单独的 Epic。对于第二个史诗,SIGN_IN_FAILURE
操作将在 signInFailureEpic
收到之前已经到达您的减速器,因此它们将被更新。如果您在 signInRequestEpic
中执行此操作,则操作还不会到达减速器。
商店更新并出现在同一个史诗中是可能的,但它开始变得毛茸茸,所以我不打算展示如何 ;)
没用过React Native,但你能做这样的事吗?然后在 AuthService.login()?
的 catch 中调度这个动作
export const toggleAlert = action$ =>
action$.ofType(OPEN_ERROR_TOAST)
.map(action => Alert.alert('Invalid',action.payload))
.switchMap(alert => {
alert.open();
return action$
.ofType('CLOSE_ERROR_TOAST')
.do(_ => alert.close())
})
我在我的 React Native 应用程序中使用 redux observable,如果凭据无效,我想在我的登录屏幕上显示一个 React Native 警报对话框。我可以在我的史诗中触发警报但在史诗中我只能 return 一个可观察的,那么如何使用 redux 可观察的来实现这个?
- 更新 01
验证码:
export const signInFailure = (payload) => {
return {
type: SIGN_IN_FAILURE,
payload
}
};
const signInSuccessActions = (payload) => {
return Observable.concat(
Observable.of({type: SIGN_IN_SUCCESS, payload}),
Observable.of({type: 'Navigation/NAVIGATE', routeName: 'MainTabView'})
);
};
export const signInRequestEpic = action$ =>
action$.ofType(SIGN_IN_REQUEST)
.mergeMap(action => AuthService.login(action.email, action.password)
.flatMap(payload => payload.status === 200 ? signInSuccessActions(payload) : signInFailure(payload))
.catch(error => Observable.of({
type: SIGN_IN_FAILURE,
error
}))
);
在 React Native 中使用警报 api 只是 1 行
import {Alert} from "react-native";
Alert.alert(
'Invalid',
'Email or password incorrect',
)
更好的方法是在减速器中为 SIGN_IN_FAILURE 设置一个状态以及原因。在登录屏幕中使用这些并在 componentWillReceiveProps 中显示警报或在 render 方法中显示自定义模式错误消息 像这样
class LoginScreen{
componentWillMount(){
this.componentWillReceiveProps(this.props);
}
componentWillReceiveProps(nextProps){
const { loginError } = nextProps.loginState;
if(loginError){
Alert.alert('Invalid','Email or password incorrect')
}
}
render() {
const { loginError } = this.props.loginState
<View>
<Modal visible={loginError}>
</Modal>
</View>
}
}
const mapStateToProps = (state) => {
return {
loginState: state.login,
};
};
LoginScreen = connect(mapStateToProps)(LoginScreen);
export default LoginScreen;
确保在警报对话框关闭后重置 loginError redux 状态
旁注:大多数问题实际上只是普通的 RxJS questions in disguise,并不特定于 redux-observable;这几乎将所有内容都推迟到常规 RxJS。如果您能够将问题概括为普通的 RxJS,而无需 redux-observable 术语,找到答案通常会更容易,因为有大量的 RxJS 资源以及 Whosebug、Gitter 等用户可以提供帮助。
有几种方法可以做到。
在您现有的 Epic 中执行此操作
您可以使用 .do()
operator 产生不以任何方式影响操作流的副作用——比如只显示一个警告框而不进行任何确认。
export const signInRequestEpic = action$ =>
action$.ofType(SIGN_IN_REQUEST)
.mergeMap(action =>
AuthService.login(action.email, action.password)
.flatMap(payload => payload.status === 200
? signInSuccessActions(payload)
: signInFailure(payload)
)
.do({
error: ({ payload }) =>
Alert.alert('Invalid', `Sign in failed: ${payload.message}`)
})
.catch(error => Observable.of({
type: SIGN_IN_FAILURE,
error
}))
);
您也可以在 return SIGN_IN_FAILURE
的流之前在 .catch()
中执行此操作,但我个人喜欢将副作用分开,使它们更加突出。但这是:
.catch(error => {
Alert.alert('Invalid', `Sign in failed: ${error.message}`);
return Observable.of({
type: SIGN_IN_FAILURE,
error
});
})
在新史诗
中完成如果您希望从 signInRequestEpic
中抽象出这种副作用,您可以创建另一个只监听失败的史诗,并使用 .do()
显示警报,然后使用 .ignoreElements()
运算符忽略匹配的动作,因为这个史诗不需要发出任何东西。
export const signInFailureEpic = action$ =>
action$.ofType(SIGN_IN_FAILURE)
.do(({ payload }) =>
Alert.alert('Invalid', `Sign in failed: ${payload.message}`)
)
.ignoreElements();
你应该使用哪一个?这取决于。如果您希望在 之前 更新您的 redux 商店,则显示警报,那么您肯定会想要使用单独的 Epic。对于第二个史诗,SIGN_IN_FAILURE
操作将在 signInFailureEpic
收到之前已经到达您的减速器,因此它们将被更新。如果您在 signInRequestEpic
中执行此操作,则操作还不会到达减速器。
商店更新并出现在同一个史诗中是可能的,但它开始变得毛茸茸,所以我不打算展示如何 ;)
没用过React Native,但你能做这样的事吗?然后在 AuthService.login()?
的 catch 中调度这个动作export const toggleAlert = action$ =>
action$.ofType(OPEN_ERROR_TOAST)
.map(action => Alert.alert('Invalid',action.payload))
.switchMap(alert => {
alert.open();
return action$
.ofType('CLOSE_ERROR_TOAST')
.do(_ => alert.close())
})