Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert from recompose to hooks?

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);

like image 904
Darron Avatar asked Apr 02 '19 01:04

Darron


2 Answers

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`);
  }
}
like image 63
Edan Chetrit Avatar answered Oct 17 '22 17:10

Edan Chetrit


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 .

like image 26
estebane97 Avatar answered Oct 17 '22 18:10

estebane97