skip to Main Content

I am integrating firebase in a slice. I have the extra reducers for loginAsync. If I enter incorrect details, it says pending, then success. It also doesn’t catch the error thrown by firebase.

export const loginAsync = createAsyncThunk('user/login', async (credentials: ILoginCredentials) => {
  signInWithEmailAndPassword(
    auth,
    credentials.email, 
    credentials.password
  )
    .then((userCredential) => {
      const user = userCredential.user
      return user
    })
    .catch((error) => {
      console.log('failed')
      return isRejectedWithValue(error.message)
    })
})

This is the builders in my slice

extraReducers: (builder) => {
  builder.addCase(loginAsync.pending, (state, action) => {
    console.log('pending')
    state.loading = 'pending'
  })
  builder.addCase(loginAsync.fulfilled, (state, action) => {
    state.user = action.payload
    state.loading = 'succeeded'
    console.log(state.loading)
  })  
  builder.addCase(loginAsync.rejected, (state, action) => {
    state.loginError = action.error.message
    state.loading = 'failed'
    console.log('failed')
  })

How do I correctly catch the error and set it in the slice state? Why is the rejected signin going into the fulfilled builder?

enter image description here

3

Answers


  1. Chosen as BEST ANSWER

    the firebase loginwithemailandpassword needs to be awaited and stored in a variable, then return the response

    export const loginAsync = 
    createAsyncThunk('user/login',async(credentials:ILoginCredentials)=>{
    const response = await signInWithEmailAndPassword(auth,credentials.email, 
    credentials.password)
    return response.user
    
    })
    


  2. The loginAsync thunk action creator attempts to sign in a user using the provided credentials. If the sign-in is successful, it returns the user object as the fulfilled value of the action. If an error occurs during the sign-in process, it logs the error and returns the error message as the rejected value of the action. This allows the corresponding reducer cases to handle both successful and failed login attempts in the slice state.


    export const loginAsync = createAsyncThunk('user/login', async (credentials: 
    ILoginCredentials, { rejectWithValue }) => {
    try {
    const userCredential = await signInWithEmailAndPassword(auth, credentials.email, 
    credentials.password);
      const user = userCredential.user;
      return user;
     } catch (error) {
    console.log('failed');
    return rejectWithValue(error.message);
     }
    });
    
    Login or Signup to reply.
  3. The issue here is that that loginAsync action isn’t actually returning a value, so the implicitly returned Promise is returned and since there were no uncaught errors or Promise rejections the function automatically resolves.

    Either return the Promise chain so the resolved value or rejectWithValue is returned:

    export const loginAsync = createAsyncThunk(
      'user/login',
      (credentials: ILoginCredentials, { rejectWithValue }) => {
       return signInWithEmailAndPassword( // <-- return Promise chain!
          auth,
          credentials.email, 
          credentials.password
        )
          .then((userCredential) => {
            return userCredential.user;
          })
          .catch((error) => {
            console.log('failed');
            return rejectWithValue(error.message);
          })
    });
    

    Or convert the logic to use async/await/try/catch instead of the Promise chain:

    export const loginAsync = createAsyncThunk(
      'user/login',
      async (credentials: ILoginCredentials, { rejectWithValue }) => {
        try {
          const { user } = await signInWithEmailAndPassword(
            auth,
            credentials.email, 
            credentials.password
          );
          return user;
        } catch(error) {
          console.log('failed');
          return rejectWithValue(error.message);
        }
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search