1

I am using HOC(Layout component here) to wrap my custom component. The Layout component contains Header and sidebar. On clicking link, it will be rendering the respective component. But my problem is that with every route, my HOC gets rendered as route target component is wrapped in this HOC. How can I make my HOC render only once. Example Snippet.

App.js

<Router>
<Switch>

<PrivateRoute path="routeOne" component={RouteOne}/>
<PrivateRoute path="routeTwo" component={RouteTwo}/>

</Switch>
</Router>

RouteOne.js

import React from "react"
import Layout from "/hoc"
const RouteOne  = () =>{
return({..jsx..})
}
export default Layout(RouteOne)

Layout.js

const Layout(WrappedComponent) => {
 const userDetails = useSelector(state);
 useEffect(()=>{
 dispatch(fetchSomething())
        },[dispatch])
    

 return ( <HeaderNavbarUILayout header={<Header 
 username={userDetails.userName}> 
 content={<WrappedComponent/>);
                }
export default Layout

I want to render my HOC component only once. How can I do that?

2 Answers2

0

EDIT: I would follow this pattern https://simonsmith.io/reusing-layouts-in-react-router-4

const DefaultLayout = ({component: Component, ...rest}) => {
  return (
    <Route {...rest} render={matchProps => (
      <div className="DefaultLayout">
        <div className="Header">Header</div>
          <Component {...matchProps} />
        <div className="Footer">Footer</div>
      </div>
    )} />
  )
};

then where you would normally define routes, replace it with this:

<DefaultLayout path="/" component={SomeComponent} />

I would take a look at the following docs:

how to use useEffect

https://reactjs.org/docs/hooks-reference.html#useeffect

how to implement should component update

https://reactjs.org/docs/hooks-faq.html#how-do-i-implement-shouldcomponentupdate

conditionally firing an effect

```
useEffect(
  () => {
    ...
    };
  },
  [whatever you're watching],
);
```
c0de
  • 819
  • 2
  • 9
  • 21
  • Along with this, being a novice React developer, I would like to know whether my approach was the right one. Layout Components are not supposed to re render at every route change. At the same time I want to reuse the Layout component to wrap my feature component, the reason why I made it an HOC. – know_a_guy_hu_knows_anothr_guy Jun 21 '20 at 08:05
  • it would really help if you could share a minimum reproducible example. some questions that come to mind, did you confirm that your layout is getting re-rendered on route change? alternatively, i found a pattern that seems to be pretty reasonable and addresses your problem https://simonsmith.io/reusing-layouts-in-react-router-4 – c0de Jun 21 '20 at 08:30
  • Thankyou for suggesting me that link. But the difference here is that I'm using an hoc for Layout component. ex: const userProfile = ()=>{ ... } export Layout(userProfile) So that user profile comes inside the content inside the layout. To answer your question, Yes I did confirm re rendering by putting a console log. Apart from that in each route change, the screen seems to refresh confirming it. In the useEffect(), I am dispatching an action as well to load user information also I'll try to edit my question with some more information now – know_a_guy_hu_knows_anothr_guy Jun 21 '20 at 08:49
  • it seems like you are coupling layout with things that are specific to the HOC. could you de-couple and follow the 'reusing layouts' pattern that serves your HOC wrapped component? – c0de Jun 21 '20 at 11:04
0

The hoc being wrapped around is rendered every time and that is expected. But the React's diffing algorithm will render only the changed DOM elements. The problem here was the dispatch is being called every time when the Layout page is rendered and the state gets updated and the particular DOM hence gets updated. This gives an impression of "reload" effect. Dispatching the action conditionally will do the trick. Dispatch only when the state changes.