Home > Net >  Redux-observable dispatching multiple actions
Redux-observable dispatching multiple actions

Time:02-10

I'm learning to use redux-observable and RxJS in react-native then I face a problem with dispatching multiple actions after performing a Firestore get document request.

This is my epic:

const getUserEpic: Epic = action$ => {
  return action$.pipe(
    filter(signIn.match),
    switchMap(action => {
      let usecase = container.resolve<SignInUseCase>('SignInUseCase');
      return concat(
        of(signInBegin()),
        usecase.call(action.payload).pipe(
          map(res => {
            if (res !== undefined) return saveUser(res);
            return signInFailed();
          }),
        ),
      );
    }),
  );
};

Basically, I'm trying to dispatch many actions after an action named "signIn" is dispatched. The "usecase" is performing a Firestore get document. After the response is received, I want to dispatch two actions, "saveUser" and "signInSuccess". However, if the response is undefined, action "signInFailed" must be dispatched instead of those two above.

The code should be something like this:

...
        usecase.call(action.payload).pipe(
          map(res => {
            if (res !== undefined) 
               return {
                   saveUser(res);
                   signInSuccess();
               }
            return signInFailed();
          }),
        ),

Please help me correct the code! Thank you for spending your time!

Btw, this is the SignInUseCase:

@injectable()
export class SignInUseCase implements UseCase<SignInResult, any> {
  constructor(
    @inject('AuthenticationRepository')
    private readonly authenticationRepository: AuthenticationRepository,
  ) {}

  call(param?: any): Observable<SignInResult> {
    return this.authenticationRepository.signIn(param);
  }
}

The implementation of AuthenticationRepository:

export class AuthenticationRepositoryImpl implements AuthenticationRepository {
  signIn(credential: any): Observable<SignInResult> {
    return from(getUser(credential.phone_number));
  }
}

And this is the function "getUser" which get doc from Firestore:

export const getUser = async (phoneNumber: string) => {
  const doc = await firestore()
    .collection('users')
    .doc(phoneNumber)
    .get()
    .catch(e => {
      Alert.alert('Error: ', e);
    });

  return doc.data();
};

CodePudding user response:

You can return an array in a switchMap, so the solution is simple:

    usecase.call(action.payload).pipe(
      switchMap(res => {
        if (res !== undefined) 
           return [
               saveUser(res),
               signInSuccess()
           ]
        return [signInFailed()]
      }),
    ),

This will emit all the actions in the array.

Remember that if you use switchMap, then everything you return from it must be an "ObservableLike". An Array is an ObservableLike, an Observable too, but you can't return a single action without wrapping it.

  • Related