Search code examples
javascriptnode.jsreactjsreact-hookslifecycle

Why useEffect gets executed before child compenents rendered?


i have unexpected behaviour. "user" variable that i declared at the top of App compenent is null by default.

At the first start or refresh of path=/, useEffect of App compenent gets executed before child compenent which is Login, What is the reason of this behaviour ?

App.js

import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'
import { useAuthContext } from './hooks/useAuthContext'
import { useEffect }from 'react'

// pages & components
import Home from './pages/Home'
import Login from './pages/Login'
import Signup from './pages/Signup'
import Navbar from './components/Navbar'

function App() {
  const { user } = useAuthContext()


  useEffect(() => {
    console.log("App useffect")

  }, [])


  return (
    <div className="App">
      <BrowserRouter>
        <Navbar />
        <div className="pages">
        {console.log("Route main")}
          <Routes>
            <Route 

              path="/"
              element={user ? <Home /> : <Navigate to="/login" /> } 
            />
            <Route 
              path="/login" 
              element={!user ? <Login /> : <Navigate to="/" />} 
            />
            <Route 
              path="/signup" 
              element={!user ? <Signup /> : <Navigate to="/" />} 
            />
          </Routes>
        </div>
      </BrowserRouter>
    </div>
  );
}

export default App;

Login.js

import { useEffect }from 'react'

const Login = () => {

  console.log('Login here:')


  useEffect(() => {
    console.log("Login here:' useffect")

  }, [])



  return (
        <div>Login</div>
  )
}

export default Login

Solution

  • This is what <Navigate /> simply looks like,

    function Navigate() {
      React.useEffect(
        () => navigate(JSON.parse(jsonPath), { replace, state, relative }),
        [navigate, jsonPath, relative, replace, state]
      );
    
      return null;
    }
    

    It also uses a useEffect to handle the side-effect ( replace the url ) and the render phase of the <Navigate /> returns just null.

    So it works as expected. It renders your App, then It renders your <Navigate /> which returns null. Rendering completed and then it executed the side effects. Then after all of that, the side effect in the <Navigate /> is the one which causes to render <Login /> page.