'How to trigger useEffect before render?
I am using axios to fetch data and then want to render the component. For that, I have loading which gets set to true when fetching and to false when all the data has come. But I am getting error. Is there a way to trigger useEffect before rendering of component ?
Following is the code:
GithubReducer.js
import {
SET_USERS,
CLEAR_USERS,
SET_LOADING,
SET_USER,
CLEAR_USER,
} from "../types";
const GithubReducer = (state, action) => {
switch (action.type) {
case SET_USERS: {
return { ...state, users: action.payload };
}
case CLEAR_USERS: {
return { ...state, users: [] };
}
case SET_LOADING: {
return { ...state, loading: action.payload };
}
case SET_USER: {
return { ...state, user: action.payload };
}
case CLEAR_USER: {
return { ...state, user: null };
}
default:
return state;
}
};
export default GithubReducer;
GithubState.js
import React, { useReducer } from "react";
import axios from "axios";
import {
SET_USERS,
CLEAR_USERS,
SET_LOADING,
SET_USER,
CLEAR_USER,
} from "../types";
import GithubReducer from "./GithubReducer";
import GithubContext from "./GithubContext";
const GithubState = (props) => {
const initialState = {
loading: false,
users: [],
user: null,
};
const [state, dispatch] = useReducer(GithubReducer, initialState);
const setLoading = (val) => dispatch({ type: SET_LOADING, payload: val });
const getGithubUsers = async () => {
setLoading(true);
dispatch({ type: CLEAR_USER });
const res = await axios.get(`https://api.github.com/users`);
dispatch({
type: SET_USERS,
payload: res.data,
});
setLoading(false);
};
const clearUsers = () => {
dispatch({ type: CLEAR_USERS });
};
const searchUsersWithName = async (username) => {
setLoading(true);
const res = await axios.get(
`https://api.github.com/search/users?q=${username}`
);
dispatch({ type: SET_USERS, payload: res.data.items });
setLoading(false);
};
const fetchGithubUserProfile = async (username) => {
setLoading(true);
const res = await axios.get(`https://api.github.com/users/${username}`);
dispatch({ type: SET_USER, payload: res.data });
setLoading(false);
};
return (
<GithubContext.Provider
value={{
getGithubUsers,
clearUsers,
searchUsersWithName,
fetchGithubUserProfile,
users: state.users,
loading: state.loading,
user: state.user,
}}
>
{props.children}
</GithubContext.Provider>
);
};
export default GithubState;
User.js
import React, { useContext, useEffect } from "react";
import { useParams } from "react-router-dom";
import GithubContext from "../../context/github/GithubContext";
import Spinner from "../layout/Spinner";
const User = () => {
const { fetchGithubUserProfile, user, loading } = useContext(GithubContext);
const { username } = useParams();
useEffect(() => {
fetchGithubUserProfile(username);
// eslint-disable-next-line
}, []);
if (loading) return <Spinner />;
else {
return (
<div className="user">
<button>Go Back</button>
<section className="about">{user.login}</section>
</div>
);
}
};
export default User;
And, this is the error I am getting:
TypeError: Cannot read properties of null (reading 'login')
User
D:/anubh/Desktop/github-finder/src/components/users/User.js:21
18 | return (
19 | <div className="user">
20 | <button>Go Back</button>
> 21 | <section className="about">{user.login}</section>
| ^ 22 | </div>
23 | );
24 | }
Solution 1:[1]
Very simple. You can't. useEffect runs after componentDidMount, or after the JSX has been rendered.
Here is a solution. Render your JSX conditionally depending on state, which you can set once your data is retrieved.
return (
{data ? <MyComponent /> : null}
)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Arcanus |
