使用redux observable显示警告框

时间:2017-04-03 21:31:48

标签: react-native react-redux redux-observable

我在反应原生应用程序中使用redux observable,在我的登录屏幕上,如果凭据无效,我想显示反应本机警报对话框。我可以在我的史诗中发出警报但是在史诗中我只能返回一个可观察的,所以如何使用redux observable实现这一点?

  • 更新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
        }))
    );

在反应原生中使用警报api只是1个班次

import {Alert} from "react-native";

 Alert.alert(
        'Invalid',
        'Email or password incorrect',
    )

3 个答案:

答案 0 :(得分:5)

旁注:大多数问题实际上只是正常的RxJS questions in disguise,并非特定于redux-observable;它几乎把所有东西都推迟到普通的RxJS。如果您能够将问题概括为普通的RxJS,而没有使用redux可观察的术语,那么找到答案通常会更容易,因为有大量的RxJS资源以及StackOverflow,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
        }))
    );

您还可以在返回.catch()的流之前在SIGN_IN_FAILURE内进行此操作,但我个人希望将副作用分开以使其更突出。但这就是:

.catch(error => {
  Alert.alert('Invalid', `Sign in failed: ${error.message}`);

  return Observable.of({
    type: SIGN_IN_FAILURE,
    error
  });
})

new Epic

中进行

如果您希望将此副作用从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中执行此操作,则该操作尚未达到减速器。

可以让商店更新并且在同一个史诗中,但它开始变得毛茸茸所以我不打算如何显示;)

答案 1 :(得分:0)

更好的方法是在减速器中为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状态

答案 2 :(得分:0)

没有使用过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())
    })