Thanks to whoever can help me. I know it's a common thing to have the issue of useEffect re rendering. However in my case I have set it to render only once with the [] brackets but it keeps re rendering everything.
I'm calling my getRepoContributors() function in my RepoItem.js component
I'm working with the github api. I'm able to display users info and users repos. But when i try to get contributors for repos of a certain user it keeps re rendering.
Can't figure it out. Lost the whole day as Github API bans me because of multiple requests and need to wait for a about an hour every time before trying again.
UPDATE: DAY 2 Still can't make it work. Now trying to render from Repos.js component. But i get an error message. I commented out in RepoItem.js what I was trying first with the useeeffect that was not working.
"Cannot update a component (GithubState
) while rendering a different component (Repos
)."
Please help! Going nuts! Here are my updated files.
GithubState.js (context provider)
import React, { useReducer } from "react";
import axios from "axios";
import GithubContext from "./githubContext";
import GithubReducer from "./githubReducer";
import {
SEARCH_USERS, SET_LOADING, CLEAR_USERS, GET_USER, GET_REPOS,
GET_CONTRIBUTORS, FILTER_REPOS, CLEAR_FILTER_REPOS
} from "../types";
let githubClientId;
let githubClientSecret;
.....
.....
const GithubState = (props) => {
const initialState = {
users: [],
user: {},
repos: [],
contributors: [],
loading: false,
filteredRepos: null,
error: null,
};
const [state, dispatch] = useReducer(GithubReducer, initialState);
//Search Users
const searchUsers = async (text) => {
setLoading();
const res = await axios.get(
`https://api.github.com/search/users?q=${text}&client_id=${githubClientId}&client_secret=${githubClientSecret}`
);
//res.data.items is response from Github API
dispatch({
type: SEARCH_USERS,
payload: res.data.items,
});
};
//Clear Users
const clearUsers = () => {
dispatch({ type: CLEAR_USERS });
};
//Set Loading
const setLoading = () => {
dispatch({ type: SET_LOADING });
};
//Get 1 User
const getUser = async (username) => {
setLoading();
const res = await axios.get(
`https://api.github.com/users/${username}?client_id=${githubClientId}&client_secret=${githubClientSecret}`
);
console.log(`getUser res.data`, res.data);
dispatch({ type: GET_USER, payload: res.data });
};
//Get Repos
const getUserRepos = async (username) => {
setLoading();
const res = await axios.get(
`https://api.github.com/users/${username}/repos?sort=created:asc&client_id=
${githubClientId}&client_secret=
${githubClientSecret}`
);
console.log(`getUserRepos res.data`, res.data);
dispatch({
type: GET_REPOS,
payload: res.data,
});
};
// Get Repo Contributors
const getRepoContributors = async (full_name) => {
setLoading();
const res = await axios.get(
`https://api.github.com/repos/${full_name}/contributors?client_id=${githubClientId}&client_secret=${githubClientSecret}`
);
console.log(`getRepoContributors`, res.data);
dispatch({
type: GET_CONTRIBUTORS,
payload: res.data,
});
};
//Filter Repos
const filterRepos = (text) => {
dispatch({ type: FILTER_REPOS, payload: text });
};
//Clear Filter
const clearFilterRepos = (text) => {
dispatch({ type: CLEAR_FILTER_REPOS });
};
return (
<GithubContext.Provider
value={{
users: state.users,
user: state.user,
loading: state.loading,
repos: state.repos,
contributors: state.contributors,
filteredRepos: state.filteredRepos,
error: state.error,
searchUsers,
clearUsers,
getUser,
getUserRepos,
getRepoContributors,
filterRepos,
clearFilterRepos,
}}
>
{props.children}
</GithubContext.Provider>
);
};
export default GithubState;
App.js
import React from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import GithubState from "./contexts/github/GithubState";
import Home from "./components/pages/Home";
import User from "./components/users/User";
import "./App.css";
const App = () => {
return (
<GithubState>
<Router>
<div className="App">
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/user/:login" component={User} />
</Switch>
</div>
</Router>
</GithubState>
);
};
export default App;
User.js
import React, { useContext, useEffect } from "react";
import Spinner from "../layout/Spinner";
import Repos from "../repos/Repos";
import ReposFilter from "../repos/ReposFilter";
import { Link } from "react-router-dom";
import GithubContext from "../../contexts/github/githubContext";
const User = ({ match, iconGithub }) => {
const githubContext = useContext(GithubContext);
const { getUser, loading, user, repos, getUserRepos, getRepoContributors
} = githubContext;
useEffect(() => {
getUser(match.params.login);
getUserRepos(match.params.login);
}, []);
const { name, avatar_url, location, public_repos } = user;
if (loading) return <Spinner />;
return (
<div className="userpage-container">
.........
<div className="card grid-2">
<div>
.............
<h1>{name}</h1>
<p>Location : {location}</p>
<div className="card text-center">
............
<div className="badge">
Public Repos: : {public_repos}
</div>
</div>
</div>
............
</div>
<ReposFilter />
<Repos repos={repos} />
</div>
);
};
export default User;
Repos.js
import React, { useContext, useEffect, useState } from "react";
import RepoItem from "./RepoItem";
import RepoItemPacha from "./RepoItemPacha";
import GithubContext from "../../contexts/github/githubContext";
import Spinner from "../layout/Spinner";
const Repos = () => {
const githubContext = useContext(GithubContext);
const [repoContributors, setRepoContributors] = useState();
const {
repos,
filteredRepos,
loading,
contributors,
getRepoContributors,
} = githubContext;
if (repos !== null && repos.length === 0 && !loading) {
return <h4>No repos to show</h4>;
}
return (
<div className="text-center">
<>
{repos !== null && !loading ? (
<div>
{filteredRepos !== null
? filteredRepos.map((repo) => (
<div key={repo.id} className="item">
<RepoItemPacha repo={repo} />
</div>
))
: repos.map((repo) => (
<div key={repo.id} className="item">
{repo && getRepoContributors(repo.contributors_url)}
{contributors.map((contr) => (
<div key={contr.id} className="item">
<h3>{contr.login}</h3>
</div>
))}
<RepoItemPacha repo={repo} />
</div>
))}
</div>
) : (
<Spinner />
)}
</>
</div>
);
};
export default Repos;
RepoItem.js
import React, { useEffect, useContext, useState } from "react";
import GithubContext from "../../contexts/github/githubContext";
const RepoItemPacha = ({ repo }) => {
const githubContext = useContext(GithubContext);
const [repoContributors, setRepoContributors] = useState();
const { getRepoContributors, contributors, repos } = githubContext;
// useEffect(() => {
// if (repo) {
// getRepoContributors(repo.contributors_url);
// console.log(
// `getRepoContributors(repo.contributors_url)`,
// getRepoContributors(repo.contributors_url)
// );
// }
// }, [repo]);
// useEffect(() => {
// if (contributors) {
// setRepoContributors(contributors);
// }
// }, []);
// let theContributors = [getRepoContributors(repo.full_name)];
return (
<div className="card">
<h3>
<a href={repo.html_url} target="_blank" rel="noopener noreferrer">
{repo.name}
</a>
</h3>
<h4>{repo.collaborators_url}</h4>
{/* {repoContributors &&
repoContributors.map((contr) => (
<div key={contr.id} className="item">
<h3>{contr.login}</h3>
</div>
))} */}
{repo.description && (
<p>
<strong>Description: </strong>
{repo.description}
</p>
)}
<p></p>
{repo.language && (
<p>
<strong>Language: </strong>
{repo.language}
</p>
)}
</div>
);
};
export default RepoItemPacha;