Recompose library - Tuong-Nguyen/JavaScript-Structure GitHub Wiki

Recompose is a React utility belt for function components and higher-order components. Think of it like lodash for React.

Install

npm install recompose --save

Common HOCs and utilities

  • compose(HOCs): Use to compose multiple higher-order components into a single higher-order component
  • mapProps(): Maps the current props and return "derived" props to base component
  • withState(): Help the react component stays dumb but has ability to use state
  • withHandlers(): Avoids create new handler on every render.
  • lifecycle(): Access to component lifecycle methods
  • Read more

mapProps()

mapProps(
  propsMapper: (ownerProps: Object) => Object,
): HigherOrderComponent

Example

compose(
  withRouter,
  graphql(...),
  mapProps(({ data, ...rest }) => {
    const jobs = get(data, 'jobsByEmployerId.jobs');
    const total = get(data, 'jobsByEmployerId.total');
   
    return {
      ready: !data.loading,
      listData: jobs,
      pageCount: Math.ceil(total / 20),
      ...rest,
    };
  })
)
  • mapProps() receives data from graphql HOC and populate the new props listData from data's jobsByEmployerId.jobs, pageCount from data's jobByEmployerId.total and keep the rest of props to base component

withState()

withState(
  stateName: string,
  stateUpdaterName: string,
  initialState: any | (props: Object) => any
): HigherOrderComponent
  • Add 2 prop to props of base component:
    • a state value that has state name is stateName
    • a function that has name is stateUpdaterName to update the state value
  • The state updater has 2 signatures:
stateUpdater<T>((prevValue: T) => T, ?callback: Function): void
stateUpdater(newValue: any, ?callback: Function): void

Example

const enhance = withState('counter', 'setCounter', 0);
const Counter = enhance(({ counter, setCounter }) =>
  <div>
    Count: {counter}
    <button onClick={() => setCounter(n => n + 1)}>Increment</button>
    <button onClick={() => setCounter(n => n - 1)}>Decrement</button>
  </div>
);

withHandlers()

withHandlers(
  handlerCreators: {
    [handlerName: string]: (props: Object) => Function
  } |
  handlerCreatorsFactory: (initialProps) => {
    [handlerName: string]: (props: Object) => Function
  }
): HigherOrderComponent
  • Handlers are expected a map of higher-order functions
withHandlers({
  onChange: props => event => {
    //...
  },
  onSubmit: ...
})

Example

const addCounting = compose(
  withState('counter', 'setCounter', 0),
  withHandlers({
    increment: props => () => props.setCounter(n => n + 1),
    decrement: ({ setCounter }) => () =>  setCounter(n => n - 1),
    reset: ({ setCounter }) => () => setCounter(0)
  })
)
const Counter = addCounting(({ counter, increment, decrement, reset }) =>
  <div>
    Count: {counter}
    <br/>
    <button onClick={increment}>Increment</button>
    <button onClick={decrement}>Decrement</button>
    <button onClick={reset}>Reset</button>
  </div>
);

lifecycle()

lifecycle(
  spec: Object,
): HigherOrderComponent
  • Supports entire Component API, except render() (overridden if specified)
  • Using setState to make state changes that will be propagated to the wrapped component as props.

Example

lifecycle({
  componentDidMount() {
    const { checkIfAuthed } = this.props;
    // Do they have an active session? ("Remember me")
    checkIfAuthed();
 },
 //...
})
⚠️ **GitHub.com Fallback** ⚠️