I have a higher order component that adds universal functionality to a group of similar components. For the purposes of discussion, I'll call the HOC Wrapper
and the children CompA
, CompB
, etc.
Wrapper is connect
ed, and handles the interactions with the Redux store, as well as API interactions. The data it sends is owned by the wrapped children, so I pass the API/dispatch function(s) from Wrapper into the children via props. Now CompA, CompB, etc all have a props.doStuff
function that's defined one time in Wrapper.
This is OK, but the events that determine when to call the doStuff
function are changes of the local state in CompA, CompB, etc. So I'm copy/pasting the same useEffect
s between the children...
function CompA(props) {
const [data, setData] = useState({});
useEffect( () => {
if (props.doStuffNow === true) {
props.doStuff(data);
}
}, [props.something]);
return <div>CompA</div>
}
function CompB(props) {
const [differentData, setDifferentData] = useState({});
useEffect( () => {
if (props.doStuffNow === true) {
props.doStuff(differentData);
}
}, [props.something]);
return <div>CompB</div>
}
This is not D.R.Y. and I'm really tempted to move the useEffect
etc into Wrapper class and allow CompA and CompB to extend
that class.
However, the React documentation strongly recommends composition over inheritance using higher order components. The linked article goes so far as to say they've never encountered a situation in which inheritance was better than composition.
So what am I missing? Is there a way for me to make this code DRY using HOC? Can I somehow pass the useEffect
s via props? Is the sky going to fall if I just follow my instinct: class CompA extends Wrapper
... ??
Create a new hook called useDoStuff
that performs the useEffect hook and then useDoStuff(props)
wherever you need it.
function useDoStuff(props) {
const [data, setData] = useState({}):
useEffect(...)
}
function CompA (props) {
useDoStuff(props);
...
}
function CompB (props) {
useDoStuff(props);
...
}