Search code examples
reactjsreduxreact-reduxfirebase-authenticationredux-toolkit

React: A non-serializable value was detected in the state


I'm trying to make a simple login/logout feature in my app using firebase auth rest API, I'm using redux to let user log in and logout, the user get registered perfectly in the firebase but when I hit Signup & Login button of the form, I'm getting this error 👇

enter image description here

With redux toolkit I'm wondering what's going wrong with my initialState of login function. Here is my code: -

//login-store.js
const { configureStore, createSlice } = require("@reduxjs/toolkit");

const userAuth = createSlice({
    name: "login",
    initialState: {
        token: "",
        isLoggedIn: false,
        login: (token) => {},
        logout: () => {},
    },
    reducers: {
        logginOut(state) {
            state.isLoggedIn = false;
            state.logout = () => {
                localStorage.removeItem("userLoginToken");
            };
        },
        loggingIn(state) {
            state.isLoggedIn = true;
            state.token = localStorage.getItem("userLoginToken");
            state.login = (token) => {
                return localStorage.setItem("userLoginToken", token);
            };
        },
    },
});

const authStore = configureStore({
    reducer: userAuth.reducer,
});

export const userAuthAction = userAuth.actions;

export default authStore;

And here I'm having my login and signup feature. Also there is one more problem, whenever I click New User button below the submit button, I immediately get the alert popup (written with comment below) I don't know how am I sending fetch request while switching the form...

//Login.js

import React, { useRef, useState } from "react";
import { useDispatch } from "react-redux";
import { useNavigate } from "react-router-dom";
import { userAuthAction } from "../store/login-store";
import classes from "./pages.module.css";

export default function Login() {
    const dispatch = useDispatch();
    const [isLogin, setIsLogin] = useState(true);
    const navigate = useNavigate();

    const emailInput = useRef();
    const passwordInput = useRef();

    const switchAuthTextHandler = () => {
        setIsLogin((prevState) => !prevState);
    };

    const loginAuthHandler = (e) => {
        e.preventDefault();
        const enteredEmailValue = emailInput.current.value;
        const enteredPasswordValue = passwordInput.current.value;

        let authUrl;

        if (isLogin) {
            // when logging in
            authUrl =
                "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=AIzaSyB3Mbv38Ju8c9QedQzqX3QvufTCOXhkU0c";
        } else {
            // when signing up
            authUrl =
                "https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=AIzaSyB3Mbv38Ju8c9QedQzqX3QvufTCOXhkU0c";
        }

        fetch(authUrl, {
            method: "POST",
            body: JSON.stringify({
                email: enteredEmailValue,
                password: enteredPasswordValue,
                returnSecureToken: true,
            }),
            headers: {
                "Content-type": "application/json",
            },
        })
            .then((res) => {
                if (res.ok) {
                    return res.json();
                } else {
                    return res.json().then((data) => {
                        // getting alert popup immediately after switching the form
                        alert(data.error.message);
                    });
                }
            })
            .then((data) => {
                dispatch(userAuthAction.loggingIn(data.idToken));
                navigate("/");
                console.log(data);
            })
            .catch((err) => {
                console.error(err.message);
            });
    };

    return (
        <div className={classes.loginWrapper}>
            <form onSubmit={loginAuthHandler}>
                <h4>{isLogin ? "Login" : "Signup"}</h4>
                <div className={classes.form_group}>
                    <label htmlFor="email">Email</label>
                    <input type="email" id="email" ref={emailInput} />
                </div>
                <div className={classes.form_group}>
                    <label htmlFor="password">Password</label>
                    <input type="password" id="password" ref={passwordInput} />
                </div>
                <div className={classes.form_group}>
                    <button type="submit">{isLogin ? "Login" : "Signup"}</button>
                </div>
                <div className={classes.form_group}>
                    <button className={classes.newUser} onClick={switchAuthTextHandler}>
                        {isLogin ? "New User?" : "Already have account"}
                    </button>
                </div>
            </form>
        </div>
    );
}

Error while siging up the new user:-

enter image description here


Solution

  • We should not store function references in the redux store. They are not serializable, and states should be serializable in redux state.