skip to Main Content

I am building a simple to do app, and I have implemented a simple conditional rendering scheme, where I log "Hello world" if user is not authenticated, and I show the page if it is authenticated. However, even when the user is logged in, the "Hello world" is still logged to the console.
Here is my code

import React, { useState, useEffect } from "react";
import Tasks from "../tasks";
import { IoIosArrowBack } from "react-icons/io";
import { Link } from "react-router-dom";
import { auth } from "../../firebase";
import { onAuthStateChanged} from "firebase/auth";

const History = ({ tasks }) => {
  const [authUser, setAuthUser] = useState(null);

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      setAuthUser(user);
    });

    return () => {
      unsubscribe();
    };
  }, []);

  return (
    <div>
      {authUser ? (<React.Fragment>
      <div className="navbar">
        <Link to="/home" className="navbar-left">
          <IoIosArrowBack style={{ fontSize: "35px" }} />
        </Link>
        <div className="navbar-right">
          <div className="navbar-subtext">Finished tasks</div>
          <div className="navbar-ut">
            {tasks.filter((t) => t.completed === true).length}
          </div>
        </div>
      </div>
      <br />
      <hr />
      <Tasks
        tasks={tasks}
        remainingTasks={tasks.filter((t) => t.completed === true).length}
        showCompleted={true}
      />
    </React.Fragment>) : (console.log("Hello World"))}
    </div>
  );
};

export default History;

2

Answers


  1. You should add a simple log statement in your component to find out how many times it renders, and the value of authUser at each rendering. It’s almost certainly the case that your component is rendering more than once:

    • First with the initial value of authUser, which will be null when the page first loads
    • Second, with the eventual value of authUser which will be an object describing the signed-in user (assuming a user was actually previously signed in).

    Firebase Auth state observers never trigger with signed-in user data when the page initially loads. They always trigger some time later after the user is known for sure to be signed in and their ID token is valid. Your component needs to be aware of this and render appropriately. Maybe use some sort of loading indicator to show that all of the information required to render the component is not yet available.

    Read:

    My personal opinion: using console.log in the middle of JSX is not a good way to debug the way a component works. Put your logging before the JSX to understand what is about to be rendered each time.

    Login or Signup to reply.
  2. To fix this, you can move the console.log statement outside of the JSX and conditionally render it based on the authUser state. Here’s the updated code:

    import React, { useState, useEffect } from "react";
    import Tasks from "../tasks";
    import { IoIosArrowBack } from "react-icons/io";
    import { Link } from "react-router-dom";
    import { auth } from "../../firebase";
    import { onAuthStateChanged} from "firebase/auth";
    
    const History = ({ tasks }) => {
      const [authUser, setAuthUser] = useState(null);
    
      useEffect(() => {
        const unsubscribe = onAuthStateChanged(auth, (user) => {
          setAuthUser(user);
        });
    
        return () => {
          unsubscribe();
        };
      }, []);
    
      if (authUser === null) {
        return null;
      }
    
      return (
        <div>
          <div className="navbar">
            <Link to="/home" className="navbar-left">
              <IoIosArrowBack style={{ fontSize: "35px" }} />
            </Link>
            <div className="navbar-right">
              <div className="navbar-subtext">Finished tasks</div>
              <div className="navbar-ut">
                {tasks.filter((t) => t.completed === true).length}
              </div>
            </div>
          </div>
          <br />
          <hr />
          <Tasks
            tasks={tasks}
            remainingTasks={tasks.filter((t) => t.completed === true).length}
            showCompleted={true}
          />
        </div>
      );
    };
    
    export default History;
    

    I’ve added a check to see if authUser is null. If it is null, the component returns null, which effectively renders nothing. This prevents the "Hello World" message from being logged when the user is not authenticated. If authUser is not null, the component continues to render the rest of its content as before.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search