React Component Mounting Twice
The problem is that the component
prop here is a function application, which yields a new class on each render. This will cause the previous component to unmount and the new one to mount (see the docs for react-router for more information). Normally you would use the render
prop to handle this, but this won't work with higher-order components, as any component that is created with a HOC application during rendering will get remounted during React's reconciliation anyway.
A simple solution is to create your components outside the ExhibitOne
class, e.g.:
const ExhibitWallOne = ExhibitHOC(WallOne);
const ExhibitWallTwo = ExhibitHOC(WallTwo);
..
export default class ExhibitOne extends Component {
..
<Route path={`${match.url}/wall-one`} component={ExhibitWallOne} />
<Route path={`${match.url}/wall-two`} component={ExhibitWallTwo} />
..
}
Alternatively, depending on what the wrapper does, it might be possible to declare it as a normal component that renders {this.props.children}
instead of the parameter <ComposedComponent/>
, and wrap the components in each Route
:
<Route path={`${match.url}/wall-one`}
render={(props) => <Wrap><WallOne {...props}/></Wrap>}
/>
Note that you'll need to use render
instead of component
to prevent remounting. If the components don't use routing props, you could even remove {...props}
.
Here in 2020, this was being caused by <React.StrictMode>
component that was wrapped around the <App />
in new versions of Create React App. Removing the offending component from index.js
fixed the double mount problem for all of my components. This was by design, but it was annoying and misleading to see console.log() twice for everything.
For Next.js, in next.config.js
, set reactStrictMode:false
.
If you use 'Hidden Material UI React', it mounts your component every time you call it. For example, I wrote the below one:
<Hidden mdDown implementation="css">
<Container component="main" maxWidth="sm">
{content}
</Container>
</Hidden>
<Hidden smUp implementation="css">
{content}
</Hidden>
It invokes both contents in both hidden components. it took me a lot of time.