Home > Software engineering >  How to use firebase authentication with Redux Toolkit and createAsyncThunk?
How to use firebase authentication with Redux Toolkit and createAsyncThunk?

Time:07-22

I'm trying to implement Firebase Authentication via Redux Toolkit. But I think I'm missing something due to lack of knowledge.

My monitorAuthChange returns undefined.

I have two separate files - first list of firebase functions, second Redux Toolkit slice.

import {
  createUserWithEmailAndPassword,
  onAuthStateChanged,
} from "firebase/auth";
import { auth } from "./firebaseConfig";

export const createAccount = async (email, password) => {
  try {
    await createUserWithEmailAndPassword(auth, email, password);
  } catch (error) {
    console.log(error);
  }
};

export const monitorAuthChange = () => {
  onAuthStateChanged(auth, (user) => {
    if (user) {
      return true;
    } else {
      return false;
    }
  });
};
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { createAccount, monitorAuthChange } from "../../service/userServices";

export const createUser = createAsyncThunk(
  "users/createUser",
  async ({ username, password }) => {
    await createAccount(username, password);
  }
);

const initialState = { loginStatus: false };

const userSlice = createSlice({
  name: "users",
  initialState,
  reducers: {},
  extraReducers: {
    [createUser.fulfilled]: (state, action) => {
      const result = monitorAuthChange();
      state.loginStatus = result;
    },
    [createUser.rejected]: (state, action) => {
      state.loginStatus = false;
    },
  },
});

export const selectAllUsers = (state) => state.users;
export default userSlice.reducer;

Two things make me confused:

    1. Thunk works - it creates account and I see it in Firebase. Do I need to track result of request in a different way?
    1. If add console.log(user) inside monitorAuthChange it logs data depends if user was created or not. But still returns undefined. Would appreciate any hint or advice or article to read to understand my mistake. Thanks in advance.

CodePudding user response:

It seems you want to track user auth with onAuthStateChanged You have plenty way to plug this callback to redux.

You cannot call monitorAuthChange inside the reducer as they must be pure.

Using global store

// users.slice.ts
const userSlice = createSlice({
  name: "users",
  initialState,
  reducers: {
    setLoginStatus: (state, action) {
      state.loginStatus = action.payload;
    }
  },
  extraReducers: {
    [createUser.fulfilled]: (state, action) => {
      state.loginStatus = true;
    },
    [createUser.rejected]: (state, action) => {
      state.loginStatus = false;
    },
  },
});

// trackUserAuth.ts
onAuthStateChanged(auth, (user) => {
    if (user) {
      store.dispatch(setLoginStatus(true))
    } else {
      store.dispatch(setLoginStatus(true))
    }
});

Using hooks

export const useAuth = () => {
  const dispatch = useDispatch();
  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      if (user) {
        dispatch(setLoginStatus(true))
      } else {
        dispatch(setLoginStatus(true))
      }
    });
    return unsubscribe;
  }, []);
}
  • Related