My company is using recompose as our state management tool. We are refactoring our application to use hooks. For the code below, how would you replace recompose component with react hook components?
I understand that withState becomes useState, such as:
withState('something', 'setSomething', null)
becomes
const [something, setSomething] = useState(null);
What would withProps
, withHandlers
, compose
, hoistStatics
and lifecycle
change to?
How would mapStateToProps
and mapDispatchToProps
work?
import { compose, hoistStatics, withHandlers, withState, withProps, lifecycle } from 'recompose';
import { connect } from 'react-redux'
import myComponent from './myComponent'
const mapStateToProps = (state, props) => {
return {
}
};
const mapDispatchToProps = (dispatch) => {
return bindActionCreators({
}, dispatch)
};
const enhancer = compose(
connect(mapStateToProps,mapDispatchToProps),
withProps(props => ({
myProp: props.myProp,
})),
withState('something', 'setSomething', null),
withState('somethingElse', 'setSomethingElse', null),
withHandlers({
myFunction: () => () => {
console.log(`I need help`);
}
}),
lifecycle({
componentDidMount() {
},
componentDidUpdate() {
}
})
);
export default hoistStatics(enhancer)(myComponent);
Citing Dan Abramov:
To get productive, you need to “think in effects”, and their mental model is closer to implementing synchronization than to responding to lifecycle events.
We can not replace hooks and hocs 1:1, since they are different programming models. Still, we can try migrating by:
withProps
- can be replaced as const inside the component
withHandlers
- can be replaced as an arrow function inside the component
lifecycle
- https://stackoverflow.com/a/55502524/3439101
A simple example (not with all the cases):
with hocs
const enhancer = compose(
withProps(props => ({
myProp: props.myProp,
})),
withState('something', 'setSomething', null),
withHandlers({
myFunction: () => () => {
console.log(`I need help`);
}
}),
lifecycle({
componentDidMount() {
console.log('mounted')
}
})
);
with hooks
const MyComponent = props => {
const [something, setSomthing] = useState(null)
useEffect(() => {
console.log('mounted')
}, [])
const myProp = props.myProp
const myFunction = () => {
console.log(`I need help`);
}
}
You are right, withState
can be replaced with useState
.
For Redux part, React recommend to keep using the API in the same way you have been using it, but you should take this out from compose
. In react-redux
v7 a new hook will be implemented for this.
Now withHandlers
, can be replaced with plain javascript functions, add it to your component or any other file
Before:
withHandlers({
myFunc() => () => {console.log('hello')}
})
Now:
const myFunc = () => {console.log('hello')}
Last but not least, componentDidMount
and componendDidUpdate
will need to be replaced with useEffect. Here there will be a little bit of reading to understand how this works but it is not hard. You will create effects that are basically functions that run every single render, you can pass a second parameter if you want this to run only when something has changed, similar to componentDidUpdate
or an empty array if you want to run only once similar to componentDidMount
. Do not think of effects as replacement of lifecycle events, but you can achieve the same results. Have a look of this article I found it quite useful.
There are few other hooks available, I found useContext
, useCallback
and useReducer
very nice to use .
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With