简体   繁体   中英

Trigger a rerender of parent component when a child component is rendered

I am using the following material-ui theme Paperbase and within the Header.js component, I have the following useEffect hook:

const [temperature, setTemperature] = useState([]);

  const getTemperature= async () => {
    try {

      const response = await fetch('/get-temperature')
      const tempData = await response.json();

      setTemperature(tempData);
    } catch (err) {
      console.error(err.message);
    }
  };

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

The main purpose of this, is to display the current temperature as info, within the header component, which gets displayed at first page load/render.

Now within my App.js below, I have the following return setup where the above Header component is called.

return (
    <Router>
      <UserProvider myinfo={myinfo}>
        <Switch>
          <Route path="/">
              <ThemeProvider theme={theme}>
                <div className={classes.root}>
                  <CssBaseline />
                  <nav className={classes.drawer}>
                    <Hidden xsDown implementation="css">
                      <Navigator />
                    </Hidden>
                  </nav>
                  <div className={classes.app}>
                    <Header
                      onDrawerToggle={handleDrawerToggle}
                    />
                    <main className={classes.main}>
                      <Switch>
                        <Route exact path="/new-user"
                          render={(props) => <Content key={props.location.key} />}
                        />
                        <Route exact path="/view-results"
                          render={(props) => <ViewResults key={props.location.key} />}
                        />
                      </Switch>
                    </main>
                  </div>
                </div>
              </ThemeProvider>
          </Route>
        </Switch>
      </UserProvider>
    </Router>
);

My question is, how can I trigger a rerender of Header (parent) whenever the user routes to either /new-user or /view-results which in turn calls either Content.js or ViewResults.js , inorder to make the useEffect in Header.js refresh the data, from the REST api fetch and display the latest temperature in the header again?

Ideally anytime Content.js or ViewResults.js is rendered, ensure that Header.js getTemperature() is called.

Any help would be much appreciated.

Your current code is pretty close to a multi layout system. As being a component child of Route , you can access the current location via useLocation() or even the native window.location.pathname .

This is my example of multi layout React app. You can try to use it to adapt to your code.

The MainLayout use a fallback route when no path is specified. It also contains a Header and include a page

 const Dispatcher = () => { const history = useHistory(); history.push('/home'); return null; }; const App = () => ( <BrowserRouter> <Switch> <Route component={Dispatcher} exact path="/" /> <Route exact path="/login/:path?" > <LoginLayout> <Switch> <Route component={LoginPage} path="/login" /> </Switch> </LoginLayout> </Route> <Route> <MainLayout> <Switch> <Route component={HomePage} path="/home" /> </Switch> </MainLayout> </Route> </Switch> </BrowserRouter> );

And here is the code for MainLayout

 const MainLayout = ({ children }) => ( <Container disableGutters maxWidth={false} > <Header location={props.location} /> <Container component="main" maxWidth={false} sx={styles.main} > {children} </Container> <Footer /> </Container> );

Now that Header can be anything. You need to put a capture in this component

 import { useLocation } from 'react-router-dom' cont Header = (props) => { const { pathname } = useLocation(); //alternatively you can access props.location useEffect(() => { if (pathname === '/new-user') { getTemperature(); } }, [pathname]); };

Note that Header is not a direct descendant of Route therefore it cannot access the location directly via props . You need to transfer in chain

Route -> MainLayout -> Header

Or better use useLocation

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM