Inside a small portion of my React/Redux/ReactRouterV4 application, I have the following component hierarchy,
- Exhibit (Parent)
-- ExhibitOne
-- ExhibitTwo
-- ExhibitThree
Within the children of Exhibit, there are about 6 different possible routes that can be rendered as well. Don't worry, I will explain with some code.
Here is my Parent Exhibit Component:
export class Exhibit extends Component {
render() {
const { match, backgroundImage } = this.props
return (
<div className="exhibit">
<Header />
<SecondaryHeader />
<div className="journey"
style={{
color: 'white',
backgroundImage: `url(${backgroundImage})`,
backgroundSize: 'cover',
backgroundRepeat: 'no-repeat',
backgroundPosition: 'center-center'
}}>
<Switch>
<Route path={`${match.url}/exhibit-one`} component={ExhibitOne} />
<Route path={`${match.url}/exhibit-two`} component={ExhibitTwo} />
<Route path={`${match.url}/exhibit-three`} component={ExhibitThree} />
<Redirect to="/" />
</Switch>
</div>
</div>
)
}
}
Basically, all its does for its job is to display one of the exhibits subcomponents, and set a background image.
Here is one of the subcomponents, ExhibitOne:
export default class ExhibitOne extends Component {
constructor(props) {
super(props)
}
render() {
const { match } = this.props
return (
<div className="exhibit-one">
<Switch>
<Route path={`${match.url}/wall-one`} component={ExhibitHOC(WallOne)} />
<Route path={`${match.url}/wall-two`} component={ExhibitHOC(WallTwo)} />
<Route path={`${match.url}/wall-three`} component={ExhibitHOC(WallThree)} />
<Route path={`${match.url}/wall-four`} component={ExhibitHOC(WallFour)} />
<Route path={`${match.url}/wall-five`} component={ExhibitHOC(WallFive)} />
<Route path={`${match.url}/wall-six`} component={ExhibitHOC(WallSix)} />
</Switch>
</div>
)
}
}
In order to cut down on typing, I decided to wrap the components in a Higher Order Component, whose purpose is to dispatch an action that will set the proper background image on the top level Exhibit parent component.
This is the Higher Order Component:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as actions from '../../actions/wall-background-image'
export default function(ComposedComponent) {
class ExhibitHoc extends Component {
componentDidMount = () => this.props.setBackgroundImage(`./img/exhibit-one/${this.getWall()}/bg.jpg`)
getWall = () => {
// this part isnt important. it is a function that determines what wall I am on, in order to set
// the proper image.
}
render() {
return <ComposedComponent />
}
}
return connect(null, actions)(ExhibitHoc);
}
On initial load of ExhibitOne, I can see that the setBackgroundImage action creator executes twice by looking at Redux Logger in the console. My initial inclination to use componentDidMount was because I thought using it would limit the action creator to execute only once. Here is a screenshot of the log:
I think I might be misunderstanding how Higher Order Components work, or maybe its some type of React Router V4 thing? Anyways, any help would be greatly appreciated as to why this executes twice.