javascriptreactjsreact-hooksreact-contextuse-context

useContext() returns null value


I am trying to use useContext to get the current logged in user details. I am getting an error in my console which says:

Uncaught TypeError: user is null
    children Animate.jsx:79
    Animate Animate.jsx:76

I am getting this error whenever I Logout. I am facing no errors in the console when I am logged in. Here is the code:

Context.js File:

import { onAuthStateChanged } from "firebase/auth";
import { useEffect, useState } from "react";
import { createContext } from "react";
import { auth } from "./firebase";

export const Context = createContext()

const ContextProviderfunc=({children})=>{
    const use={
        "mail":'history'
    }

    const [user,setuser]=useState({});
    useEffect(()=>{
        const unsubscribe = onAuthStateChanged(auth,(currentUser)=>{
            // console.log(currentUser);
            setuser(currentUser);
        })
        return ()=>{
            unsubscribe();
        }
    },[])

    return(
        <Context.Provider value={user}>
            {children}
        </Context.Provider>
    )
}

export default ContextProviderfunc

Animate.jsx File:

import React from 'react'
import {
    BrowserRouter as Router, Routes, Route, useLocation, Link
} from 'react-router-dom'
import Navbar from './Navbar'
import RecipeCard from './RecipeCard'
import Details from './Details'
import { AnimatePresence, motion } from "framer-motion"
import Add from './Add'
import clicked from './RecipeCard'
import { useState } from 'react'
import Login from './Login'
import Register from './Register'
import Protected from './Protected'
import Logout from './Logout'
import Myrecipe from './Myrecipe'
import { useContext } from 'react'
import { Context } from '../Context'




export default function Animate(props) {

    const user=useContext(Context)  
    const [pname, setpname] = useState()
    function assign(nigga) {
        setpname(nigga);
        console.log(nigga);
    }


    const location = useLocation()
    return (
        <motion.div className='all'
        >
            <AnimatePresence>

                <Routes location={location} key={location.pathname}>



                    <Route path='/Login' element={<Login />} />
                    <Route path='/Register' element={<Register />} />
                    <Route path='*' element={[<Protected><Navbar /></Protected>, <h2>Recipes</h2>,
                    <div className='recipes'>
                        {props.query ? props.query.map((object, i) => (
                            <Link className='lin' to='/Details'>
                                <div onClick={() => assign(object.Name)}>
                                    <Protected><RecipeCard
                                        src={object.src}
                                        name={object.Name}
                                        ingredients={object.Ingredients}
                                        steps={object.Steps}
                                        key={i}
                                    /></Protected>
                                </div></Link>

                        )) : "Loading"}
                        <Link className='lin' to='/Add'>
                            <div className='cardcont'>
                                <img src='https://cdn.pixabay.com/photo/2017/11/10/05/24/add-2935429_960_720.png' alt="1" className='cardimg' />
                                <div className='cardbody'>
                                    <h3>Add</h3>
                                </div>
                            </div></Link>
                    </div>
                    ]} />





                    <Route path='/MyRecipe' element={[<Protected><Navbar /></Protected>, <h2>My Recipes</h2>,
                    <Protected>
                        <div className='recipes'>
                        {props.query2 ? props.query2.map((object, i) => {

                            if(user.email==object.email){
                                console.log(user.email);

                                return(<Link className='lin' to='/Details'>
                                <div onClick={() => assign(object.Name)}>
                                    <Protected><RecipeCard
                                        src={object.src}
                                        name={object.Name}
                                        ingredients={object.Ingredients}
                                        steps={object.Steps}
                                        key={i}
                                    /></Protected>
                                </div></Link>)
                            }
                            
                                
                            
                        }
                            

                        ) : "Loading"}
                        <Link className='lin' to='/Add'>
                            <div className='cardcont'>
                                <img src='https://cdn.pixabay.com/photo/2017/11/10/05/24/add-2935429_960_720.png' alt="1" className='cardimg' />
                                <div className='cardbody'>
                                    <h3>Add</h3>
                                </div>
                            </div></Link>
                    </div>
                    </Protected>
                    ]} />


                    <Route path='/Details' element={
                        [<Navbar />, props.query ? props.query.map((object, m) => {
                            if (pname == object.Name) {

                                console.log(object.Name);
                                return (<Details
                                    src={object.src}
                                    name={object.Name}
                                    Ingredients={object.Ingredients}
                                    Steps={object.Steps}
                                    key={m}
                                />)
                            }
                        }) : "Loading"]} />


                    <Route path='/Add' element={[<Navbar />, <Add />]} />

                </Routes>
            </AnimatePresence>
        </motion.div>
    )
}

line 79 of Animate.jsx

if(user.email==object.email){
       console.log(user.email);

App.js file:

    import Navbar from './components/Navbar';
import RecipeCard from './components/RecipeCard';
import { useContext, useEffect, useState } from 'react';
import { auth, db, storage } from './firebase'
import { collection, addDoc, getDocs, doc } from "firebase/firestore";
import { async } from '@firebase/util';
import Details from './components/Details'

import Animate from './components/Animate';
import {BrowserRouter as Router, Route,Routes} from 'react-router-dom'
import Add from './components/Add';
import ContextProviderfunc from './Context';
import { Context } from './Context';







function App() {


  

  

  const [query, setquery] = useState()
  const [query2, setquery2] = useState()
  const [recipe, setrecipe] = useState()



  const add = async (e) => {
    e.preventDefault()

    try {
      const docRef= await addDoc(collection(db, "recipe"),
        {
          src: 'https://images.immediate.co.uk/production/volatile/sites/30/2017/02/Two-panna-cotta-on-plates-298e616.jpg',
          ingredients: ['Dish'],
          steps: ['Description']
        }, {
        src: 'https://imagesvc.meredithcorp.io/v3/mm/image?url=https%3A%2F%2Fstatic.onecms.io%2Fwp-content%2Fuploads%2Fsites%2F43%2F2022%2F04%2F19%2F22749-the-best-banana-pudding-mfs-366-1x1-1.jpg',
        ingredients: ['Dish'],
        steps: ['Description']

      });
      // console.log('morein');
      // console.log("Document written with ID: ", docRef.id);
    } catch (error) {
      console.log('morein');
      console.error("Error adding document: ", error);
    }

  }


  useEffect(() => {
    const getrecipe = async () => {
      const data = await getDocs(collection(db, 'recipe'))
      const data2 = await getDocs(collection(db, 'userrecipe'))

      console.log(data);
      setquery(data.docs.map((doc) => (
        {
          ...doc.data(), id: doc.id
        })
      ))
      setquery2(data2.docs.map((doc) => (
        {
          ...doc.data(), id: doc.id
        })
      ))

      console.log(query);
    };

    getrecipe();
  }, []);


  useEffect(() => {
    // searchRecipes();
  }, [])






  return (
    <div>
      <ContextProviderfunc>
      <Router>
      
      
        <Animate  query={query} query2={query2}/>
      </Router>
      </ContextProviderfunc>

    </div>
  );
}

export default App;

These two files I think are needed to debug. If any more code is needed I will provide it. Please find out the issue in the above code


Solution

  • If you set logged out user ti be null, you should not expect to retrieve email address of null. You should check (read from context) if user still logged in.

    For example :

    if(user) {
        return <div>I am logged in user and my email is {user.email} </div>
    }
    
    return <div>You are not logged In </div> 
    

    Specific to your case: check first user and then user.email to avoid Uncaught TypeError: user is null if(user && user.email === object.email) .....

    This is just a friendly suggestion, which is not related with your question: Use ===instead of == for for information you can read this page