I am creating a simple react app with router.
I want to get data from the server in one of the child components but data will be fetched only if user is logged in, so in router component I check whether user is logged in or not in useEffect hook. If it is logged in I set a variable which i access afterwords.
In the child component i send the request to server which uses that variable.
but the problem is useEffect of child component is running before useEffect of router component
Sample code for example
My router component
import React, { useEffect } from "react";
import { BrowserRouter, Switch, Route } from "react-router-dom";
import App from "./App";
// import AllWatchers from './components/AllWatchers'
export default function Router() {
useEffect(() => {
console.log("router");
}, []);
console.log("inrouter");
return (
<div>
<BrowserRouter>
<Switch>
<Route exact path="/" component={App} />
{/* <Route path='/watchers' component={AllWatchers} /> */}
</Switch>
</BrowserRouter>
</div>
);
}
** my App(child) component **
import React, { useEffect } from "react";
import "./styles.css";
export default function App() {
useEffect(() => {
console.log("App");
}, []);
console.log("inapp");
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
the output to console for this is
inrouter
inrouter
inapp
inapp
App
router
so my router component is rendering first but useEffect hook of App component is running first why?
you can view code https://codesandbox.io/s/heuristic-gagarin-ego8d?file=/src/App.js:0-319 and check the console
I don't know how to explain why this is happening, but here's a brief solution for you.
import React, { useEffect } from "react";
import "./styles.css";
export default function App() {
useEffect(() => {
const timer = setTimeout(() => {
console.log("App");
}, 2000);
return () => clearTimeout(timer);
}, []);
console.log("inapp");
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
Got it
inrouter
inrouter
inapp
inapp
router
App
If the user is logged in you could set a state like const [userLoggedIn, setUserLoggedIn] = React.useState(false)
Then the user component could be
{userLoggedIn && <UserComponent />}
This will only render UserComponent if the userLoggedIn.
Another approach would be that you pass userLoggedIn
as a prop and then only fetch the data when the that prop is true.
const UserComponent = ({userLoggedIn}) => {
React.useEffect(() => {
if(userLoggedIn) {
// Function that fetchs data.
}
}, [userLoggedIn])
}
According to docs first paint for child and parent happen at same time, and order does not matter. Your best bet would be to block the mounting of child component until API call of parent has finished loading.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.