DEV Community

NasreenKhalid
NasreenKhalid

Posted on • Updated on

React App with Firebase Authentication

Today, we will create a simple React App with the functionality of Sign In, Sign Up and Logout and we will integrate our app with firebase cloudstore in order to save the users data.

So, let's begin by creating a new react app by using the command npx create-react-app myApp and do the necessary clean-up after the app has been created which includes removing any test files, logos and commented out code.
Now, let's install firebase in our react app by typing in the command line:

npm i firebase
Enter fullscreen mode Exit fullscreen mode

Also, you need to navigate to firebase.google.com, create an account (if you don't have one) and. create a new app and then after your project is created, you go to the 'Web' icon, give a name to your app and click 'Register app' after which you will get a block of code, you need to copy that code and create a firebase.js file in the src folder of your react app and paste that code in the following manner:
Alt Text

Back to the firebase console of your project, you need to click Authentication and then 'Set sign up method', here we will Enable the first option 'Email/Password' and click Save. Please note that 'Users' tab here will show us the list of all the users who have signed up in our application.
Alt Text

Now, let's go back to our React app and start adding the necessary code to make our app functional.
First, we will create state variables for all the states that our app will have, so in App.js we will define the state variables using the useState hook:

const [user, setUser] = useState("");
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [emailError, setEmailError] = useState("");
  const [passwordError, setPasswordError] = useState("");
  const [hasAccount, setHasAccount] = useState(false);
Enter fullscreen mode Exit fullscreen mode

Now, we will create a 'components' folder in src directory and define a Login.js component there where we will have the Login form (asking for user email and password) and also Sign In/Sign Up buttons:

const Login = () => {

    return (
        <div className="login">


        <div className="loginContainer">

         <label>Username</label>
         <input type="text" autoFocus required value={email} onChange={(e)=> setEmail(e.target.value)}/>

           <p className="errorMsg">{emailError}</p>

           <label>Password</label>
           <input type="password" autoFocus required value={password} onChange={(e)=> setPassword(e.target.value)}/>
           <p className="errorMsg">{passwordError}</p>

           <div className="btnContainer">
               {hasAccount ? (
                    <>
                    <button onClick={handleLogin}>Sign In</button>
                    <p>Don't have an account ? <span onClick={() => setHasAccount(!hasAccount)}>Sign Up</span></p>
                    </>
               ) : (
<>
                    <button onClick={handleSignUp}>Sign Up</button>
                    <p>Already have an account .. <span onClick={() => setHasAccount(!hasAccount)}>Sign In</span></p>
                    </>
               )}

           </div>
        </div>
        </div>
    )
}

export default Login

Enter fullscreen mode Exit fullscreen mode

Notice that we have defined handleLogin and handleSignUp functions here but they are missing from our App.js file so let's create them:

const handleLogin = () => {
    firebasedb
      .auth()
      .signInWithEmailAndPassword(email, password)
      .catch((err) => {
        switch (err.code) {
          case "auth/Invalid-email":
          case "auth/user-disabled":
          case "auth/user-not-found":
            setEmailError(err.message);
            break;
          case "auth/wrong-password":
            setPasswordError(err.message);
            break;
          default:
        }
      });
  };
Enter fullscreen mode Exit fullscreen mode

handleLogin function uses the firebase auth() and signInWithEmailAndPassword(email, password) methods to validate the email/password user has entered and throws an error if the information entered is incorrect or not found.

Similarly, we will define the handleSignUp method:

const handleSignUp = () => {
    firebasedb
      .auth()
      .createUserWithEmailAndPassword(email, password)
      .catch((err) => {
        switch (err.code) {
          case "auth/email-already-in-use":
          case "auth/invalid-email":
            setEmailError(err.message);
            break;
          case "auth/weak-password":
            setPasswordError(err.message);
            break;
          default:
        }
      });
  };
Enter fullscreen mode Exit fullscreen mode

We will also define a handleLogout function here which is pretty simple:

  const handleLogout = () => {
    firebasedb.auth().signOut();
  };
Enter fullscreen mode Exit fullscreen mode

We will also define an authListener() method which will be activated on every auth state change and let us know if a valid user exists on our application:

const authListener = () => {
    firebasedb.auth().onAuthStateChanged((user) => {
      if (user) {
        clearInputs();
        setUser(user);
      } else {
        setUser("");
      }
    });
  };
Enter fullscreen mode Exit fullscreen mode

Also, we will need a useEffect hook which will call the authListener():

useEffect(() => {

    authListener();
  }, []);
Enter fullscreen mode Exit fullscreen mode

Now, we need to pass the props in the Login component so that we can import them in our actual component, so in the App.js file, also we will define a Home.js component which will be displayed when the user has logged in, so below we will switch on the basis of 'user' i-e if user exists then we will show the Home component otherwise we will display Login component:

return (
    <div className="App">
      {user ? (
        <Home handleLogout={handleLogout} />
      ) : (
        <Login
          email={email}
          setEmail={setEmail}
          password={password}
          setPassword={setPassword}
          handleLogin={handleLogin}
          handleSignUp={handleSignUp}
          hasAccount={hasAccount}
          setHasAccount={setHasAccount}
          emailError={emailError}
          passwordError={passwordError}
        />
      )}
    </div>
  );
Enter fullscreen mode Exit fullscreen mode

Also, don' forget to import the props in the Login component:

const Login = (props) => {

const {email, password, setEmail, setPassword, handleLogin, handleSignUp,hasAccount,setHasAccount, emailError, passwordError} = props;

    return (
        <div className="login">


        <div className="loginContainer">

           <label>Username</label>
           <input type="text" autoFocus required value={email} onChange={(e)=> setEmail(e.target.value)}/>

           <p className="errorMsg">{emailError}</p>

           <label>Password</label>
           <input type="password" autoFocus required value={password} onChange={(e)=> setPassword(e.target.value)}/>
           <p className="errorMsg">{passwordError}</p>

           <div className="btnContainer">
               {hasAccount ? (
                    <>
                    <button onClick={handleLogin}>Sign In</button>
                    <p>Don't have an account ? <span onClick={() => setHasAccount(!hasAccount)}>Sign Up</span></p>
                    </>
               ) : (
<>
                    <button onClick={handleSignUp}>Sign Up</button>
                    <p>Already have an account .. <span onClick={() => setHasAccount(!hasAccount)}>Sign In</span></p>
                    </>
               )}

           </div>
        </div>
        </div>
    )
}

export default Login
Enter fullscreen mode Exit fullscreen mode

After, you will sign up to the application and navigate to your firebase console you will see that the list of users will show the user you have just created.

This brings us to the end of our application, hope you have enjoyed reading..
Happy coding...

Discussion (2)

Collapse
manoharreddyporeddy profile image
Manohar Reddy Poreddy

Nice +1
Just a wish - if you could only show those 10 important lines with 1 or 2 fields (or bold them), and give a github url for full code.

Collapse
nasreenkhalid profile image
NasreenKhalid Author

Hi Manohar,
I will be uploading a link to the github repo very soon...thanks for you comment :)