3

我在我的 react native 应用程序中使用 redux observable,如果凭据无效,我想在我的登录屏幕上显示一个 react native 警报对话框。我可以在我的史诗中发出警报,但在史诗中我只能返回一个可观察的,那么如何使用 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
        }))
    );

在 react native 中使用 alert api 只是 1 班轮

import {Alert} from "react-native";

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

3 回答 3

4

旁注:大多数问题实际上只是变相的普通 RxJS 问题,而不是特定于 redux-observable;这几乎将所有内容都推迟到了常规的 RxJS。如果您能够将问题概括为普通的 RxJS,而无需使用 redux-observable 术语,那么找到答案通常会更容易,因为有大量的 RxJS 资源以及 StackOverflow、Gitter 等上的用户可以提供帮助。


有几种方法可以做到这一点。

在您现有的 Epic 中执行此操作

您可以使用.do()操作符来产生不以任何方式影响动作流的副作用——比如在没有任何确认的情况下显示一个警报框。

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
  });
})

的史诗中做到这一点

如果您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操作中执行此操作,则尚未到达减速器。

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

于 2017-04-03T22:15:49.303 回答
0

更好的方法是在减速器中为 SIGN_IN_FAILURE 以及原因设置一个状态。在登录屏幕中使用这些并在 componentWillReceiveProps 中显示警报或在渲染方法中显示自定义模式错误消息类似这样的东西

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 状态

于 2017-04-03T22:12:44.623 回答
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())
    })
于 2017-06-20T13:27:48.737 回答