Skip to content
Advertisement

How do I update my NavBar once a user is logged-in (from ‘log in’ to ‘profile’) using React & Firebase?

I’m new to Reactjs & Firebase, but I’ve managed to set up a signup/login system- now once the user logs in, I have them redirected back to the home page, but I want the nav bar to display ‘profile’ instead of the original ‘log in’. I know this is something to do with Conditional Rendering but I’m having trouble implementing it with Firebase.


NavBar.js

import { Link } from 'react-router-dom'

// import { AuthProvider, useAuth } from '../contexts/AuthContext'
// import firebase from 'firebase/compat/app';

const NavBar = () => {

    return (
        <header>
            <Link to = '/'>
                <img src = {require('../images/logo.png')} alt = 'logo'/>
            </Link>
            <div id = 'nav-pages'>
                <Link to='/contact'>contact</Link>
                <Link to='/about'>about</Link>
                {/* change this to a link to a profile page */}
                <Link to='/login'>log-in</Link>
            </div>
        </header>
    )
}

export default NavBar

LogIn.js

import React, { useRef, useState } from 'react'
import NavBar from '../components/NavBar'
import Footer from '../components/Footer'

import { Link, useNavigate } from 'react-router-dom';
import { AuthProvider, useAuth } from '../contexts/AuthContext'

// change to login css
import '../css/SignUp.css'

export default function Login(){

    const emailRef = useRef();
    const passwordRef = useRef();

    const { login } = useAuth();
    const [error, setError] = useState("");
    const [loading, setLoading] = useState(false);

    const navigate = useNavigate();

    async function handleSubmit(e){
        e.preventDefault();

        try {
            setError("");
            setLoading(true);
            await login(emailRef.current.value, passwordRef.current.value);
            navigate('/', {replace: true});
        } catch {
            setError('failed to sign in');
        }
        setLoading(false);
    }

    return (
        <>
            <NavBar/>
            
            <div id = 'signup'>
                <div id = 'card'>
                    <h2>log in</h2>
                    {error && <p id = 'error'>{error}</p>}
                    
                    <form onSubmit={handleSubmit} id='form'>
                        <form id='email'>
                            <p>email</p>
                            <input type='email' ref = {emailRef} required/>
                        </form>

                        <form id='password'>
                            <p>password</p>
                            <input type='password' ref = {passwordRef} required/>
                        </form>

                        <button type='submit' disabled={loading}>log in</button>
                    </form>
                </div>

                <p>need an account? <Link to='/signup'>Sign Up</Link></p>

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

AuthContext.js

import React, { useContext, useState, useEffect } from 'react'
import { auth } from '../firebase';


const AuthContext = React.createContext()

export function useAuth(){
    return useContext(AuthContext)
}

export function AuthProvider({ children }){

    const [currentUser, setCurrentUser] = useState();
    const [loading, setLoading] = useState(true);

    function signup(email, password){
        return auth.createUserWithEmailAndPassword(email, password)
    }

    function login(email, password){
        return auth.signInWithEmailAndPassword(email,password)
    }

    useEffect(() => {
        const unsubscribe = auth.onAuthStateChanged(user => {
            setCurrentUser(user)
            setLoading(false)
        })

        return unsubscribe
    }, [])

    const value = {
        currentUser,
        login,
        signup,
    }

    return (
        <AuthContext.Provider value={value}>
            {!loading && children}
        </AuthContext.Provider>
    );
}

Advertisement

Answer

I think you should be able to do this:

import { Link } from 'react-router-dom'
import { useAuth } from '../contexts/AuthContext'
// import firebase from 'firebase/compat/app';

const NavBar = () => {

    let user = useAuth().currentUser;

    return (
        <header>
            <Link to = '/'>
                <img src = {require('../images/logo.png')} alt = 'logo'/>
            </Link>
            <div id = 'nav-pages'>
                <Link to='/contact'>contact</Link>
                <Link to='/about'>about</Link>
                {user && <Link to="/profile" >Profile</Link>}
                {!user && <Link to='/login'>log-in</Link>}
            </div>
        </header>
    )
}

export default NavBar

So the line with useAuth().currentUser will get the user from the context / provider.

And the line with { user && <xxx /> } will be rendered when there is a user.

And the line with { !user && <xxx /> } will be rendered when there is no user.

Advertisement