The useeffect doesn't get triggered in one of the components , which is rendered via a route change. Adding params to dep. array didnt work

Viewed 36

Before Anyone flags this post for a duplicate post: I looked for my answer in the previous posts and couldnt get a solution by trying everything they suggested.

I am using React v18 and React-Router v6.


The route change to the user component happens in Home Component, I search for a Github profile,a list of profiles are displayed, I click on the visit profile button on the profile card, which Links me to User component.

EDIT: please find the console log output here

https://imgur.com/gallery/vbQu366

App.js

function App() {
  return (
    <GithubProvider>
      <AlertProvider>
        <Router>
          <div className="flex flex-col justify-between h-screen">

            <Navbar />

              <main className='container mx-auto px-3 pb-12'>
                <Alert />

                <Routes>
                <Route path="/" element={<Home />} />

                <Route path="/about" element={<About />} />
                <Route path="/user/:login" element={<User />} /> {/* ISSUE */}

                <Route path="*" element={<NotFound />} />

              </Routes>


              </main>

            <Footer />

          </div>
        </Router>
      </AlertProvider>
    </GithubProvider>
   
  );
}

UserItem.js (rendered from Home Component)

import { Link } from 'react-router-dom'
import PropTypes from 'prop-types'


const UserItem = ({user: {login, avatar_url}}) => {

    return (
        <div className='card shadow-md compact side bg-base-600'>
        <div className='flex-row items-center space-x-4 card-body'>
          <div>
            <div className='avatar'>
              <div className='rounded-full shadow w-14 h-14'>
                <img src={avatar_url} alt='Profile' />
              </div>
            </div>
          </div>
          <div>
            <h2 className='card-title'>{login}</h2>
            <Link
              className='text-base-content text-opacity-60'
              to={`/user/${login}`}
            >
              Visit Profile {/* TRIGGERING HERE!!!!!!!!!!! */}
            </Link>
          </div>
        </div>
      </div>
    )
}


UserItem.propTypes = {
    user: PropTypes.object.isRequired,
}

export default UserItem;

My user Component where the function getUser needs to be triggered-> The function getUsers works fine as when I used it outside an useEffect, it did give me the right response from the fetch call inside, but I need it work from within a useEffect as it's a side-effect(the same is also displayed as an error in console when I try to do this)

User.js


import React, { useEffect, useContext } from 'react'
import {FaCodepen, FaStore, FaUserFriends, FaUsers} from 'react-icons/fa'
import { Link } from 'react-router-dom'
import GithubContext from '../context/github/GithubContext'
import { useParams } from 'react-router-dom'
import Spinner from '../components/layout/Spinner'
import RepoList from '../components/repos/RepoList'


export const User = () => {

    const params = useParams()
    
    
    const { getUser, user, loading, getUserRepos, repos } =
    useContext(GithubContext)
    
    console.log("params", params, "login", params.login) // WORKS FINE
    
    
    useEffect ( () => {
        console.log("use-effect", getUser, "", params.login)
        getUser(params.login)
        getUserRepos(params.login)

    },[params.login]) // DOESNT TRIGGER WITH [] or [params.login, getUser, getUserRepos] or just [params.login]

    console.log( "user-check",user) // user object empty
    
    const {
        name,
        type,
        avatar_url,
        location,
        bio,
        blog,
        twitter_username,
        login,
        html_url,
        followers,
        following,
        public_repos,
        public_gists,
        hireable,
      } = user


      console.log("YES THIS PAGE") // Here I was checking whether page is being mounted and YES it is being mounted 


    const websiteUrl = blog?.startsWith('http') ? blog : 'https://' + blog


    if(loading){
        return <Spinner />
    }



  return (<> TYPICAL INFORMATION DISPLAY UI </>)
}
1 Answers

useEffect is called after function component is rendered. so the lines after useEffect will be called first, useEffect function will be called after. That's why you got empty 'user'

You can set another 'loading' status and display it. After useEffect got the correct user data, replace 'loading' with it.

---------update----------

Juse in case misleading:

The final reason: In the first call "" throw an error "repos is undefined". so the useEffect will not be called. you can add an undefined check here

Related