andrefurquin
andrefurquin

Reputation: 522

Child component not being updated with funcional components

I have a component where I get repositories like below:

  useEffect(() => {
    loadRepositories();
  }, []);

  const loadRepositories = async () => {
    const response = await fetch('https://api.github.com/users/mcand/repos');
    const data = await response.json();
    setUserRepositories(data);
  };
  return (
   <Repository repositories={userRepositories} /> 
  )

The child component only receives the repositories and prints them. It's like that:

const Repository = ({ repositories }) => {
  console.log('repository rendering');
  console.log(repositories);

  const [repos, setRepos] = useState(repositories);
  useEffect(() => {
    setRepos(repositories);
  }, [  ]);
  const getRepos = () => {
    repos.map((rep, idx) => {
      return <div key={idx}>{rep.name}</div>;
    });
  };
  return (
    <>
      <RepositoryContainer>
        <h2>Repos</h2>
        {getRepos()}
    </>
  );
};

export default Repository;

The problem is that, nothing is being displayed. In the console.log I can see that there're repositories, but it seems like the component cannot update itself, I don't know why. Maybe I'm missing something in this useEffect.

Upvotes: 0

Views: 26

Answers (2)

CertainPerformance
CertainPerformance

Reputation: 371233

Since you're putting the repository data from props into state, then then rendering based on state, when the props change, the state of a Repository doesn't change, so no change is rendered.

The repository data is completely handled by the parent element, so the child shouldn't use any state - just use the prop from the parent. You also need to return from the getRepos function.

const Repository = ({ repositories }) => {
  const getRepos = () => {
    return repositories.map((rep, idx) => {
      return <div key={idx}>{rep.name}</div>;
    });
  };
  return (
    <>
      <RepositoryContainer>
        <h2>Repos</h2>
        {getRepos()}
    </>
  );
};

export default Repository;

You can also simplify

useEffect(() => {
  loadRepositories();
}, []);

to

useEffect(loadRepositories, []);

It's not a bug yet, but it could be pretty misleading - your child component is named Repository, yet it renders multiple repositories. It might be less prone to cause confusion if you named it Repositories instead, or have the parent do the .map instead (so that a Repository actually corresponds to one repository array item object).

Upvotes: 1

Aleks
Aleks

Reputation: 984

Change this

 useEffect(() => {
    setRepos(repositories);
  }, [  ]);

to

 useEffect(() => {
    setRepos(repositories);
  }, [repositories]);

Upvotes: 0

Related Questions