Reputation: 12044
I'm using React Functional Components. I'm familiar with the class lifecycle, but not with the functional lifecycle. My problem is that this component is rendered before the initialization performed in useEffect().. is complete. In my return()
I check whether a state variable is true or not.
TopNav
& Main
)Error
layoutWhat is the order in which functional components are processed? I can't present then non-Error layout until the error condition has been evaluated.
function App() {
const [error, setError] = useState({});
const [userInfo, setUserInfo] = useState({});
const fetchUserInfo = async () => {
const url = 'http://myapp.com/fetchUserInfo';
try {
const response = await axios.get(url);
setUserInfo(response.data);
}
catch (error) {
setError(error);
}
}
// On initialization, fetch UserInfo
useEffect(() => {
fetchUserInfo();
}, []);
return (
<div className="App">
<Router>
<Header />
{error.message
?
<Error error={error} />
:
<div>
<TopNav userInfo={userInfo} />
<Main userInfo={userInfo} />
</div>
}
<Footer />
</Router>
</div>
);
}
Upvotes: 2
Views: 795
Reputation: 62
Your code will be executed in this order.
Upvotes: 1
Reputation: 282060
useEffect
callback function is called after the render cycle and so once your render is complete, your fetchUserInfo
call is made which is again an async operation.
What you should instead have is a loading state to let the UI wait will the API has provided as response to show an appropriate UI
function App() {
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState({});
const [userInfo, setUserInfo] = useState({});
const fetchUserInfo = async () => {
const url = 'http://myapp.com/fetchUserInfo';
setIsLoading(true);
try {
const response = await axios.get(url);
setUserInfo(response.data);
}
catch (error) {
setError(error);
}
finally {
setIsLoading(false);
}
}
// On initialization, fetch UserInfo
useEffect(() => {
fetchUserInfo();
}, []);
return (
<div className="App">
<Router>
<Header />
{isLoading? <Loader />: error.message
?
<Error error={error} />
:
<div>
<TopNav userInfo={userInfo} />
<Main userInfo={userInfo} />
</div>
}
<Footer />
</Router>
</div>
);
}
Upvotes: 2
Reputation: 841
Looking at your code, you will only get an error/data state after the async function fetchUserInfo
is resolved/rejected. You can try adding a third state loading
to signify that component has mounted but data fetching is in progress.
function App() {
const [error, setError] = useState({});
const [userInfo, setUserInfo] = useState({});
const [loading, setLoading] = useState(true)
const fetchUserInfo = async () => {
setLoading(true);
setError({})
const url = 'http://myapp.com/fetchUserInfo';
try {
const response = await axios.get(url);
setLoading(false);
setUserInfo(response.data);
}
catch (error) {
setLoading(false)
setError(error);
}
}
// On initialization, fetch UserInfo
useEffect(() => {
fetchUserInfo();
}, []);
return (
<div className="App">
<Router>
<Header />
{error.message && !loading
?
<Error error={error} />
:
<div>
<TopNav userInfo={userInfo} />
<Main userInfo={userInfo} />
</div>
}
<Footer />
</Router>
</div>
);
}
Upvotes: 1