Skip to content

Instantly share code, notes, and snippets.

@fragosti
Created January 10, 2018 07:28
Show Gist options
  • Save fragosti/1eefef6e6200f4dc3332a2ee0caac092 to your computer and use it in GitHub Desktop.
Save fragosti/1eefef6e6200f4dc3332a2ee0caac092 to your computer and use it in GitHub Desktop.
React Recompose Primer

React Recompose Primer

This primer will try to explain what recompose is by writing a non-recompose React component and then progressively refactoring it until you end up using withState from recompose.

import React, { Component} from 'react';

class MyComponent extends Component {
  state = {
    isShowingStuff: false,
  }
  
  setIsShowingStuff = (isShowing) => this.setState({ isShowingStuff: isShowing})
  
  render() {
    const { isShowingStuff } = this.state;
    return (
      <div>
        <button onClick={() => this.setIsShowingStuff(!isShowingStuff)}> Click me </button>
        <span> Some stuff </span>
        {isShowingStuff && <span> More stuff </span>}
        <span> Even some more stuff </span>
      <div>
    )
  }
}

This is fine. Lets refactor it to follow the common best practice of smart and dumb components.

import React, { Component} from 'react';

const MyDumbComponent = ({ isShowingStuff, setIsShowingStuff }) => (
    <div>
        <button onClick={() => setIsShowingStuff(!isShowingStuff)}> Click me </button>
        <span> Some stuff </span>
        {isShowingStuff && <span> More stuff </span>}
        <span> Even some more stuff </span>
    <div>
)

class MySmartComponent extends Component {
  state = {
    isShowingStuff: false,
  }
  
  setIsShowingStuff = (isShowing) => this.setState({ isShowingStuff: isShowing})
  
  render() {
    const { isShowingStuff } = this.state;
    return <MyDumbComponent isShowingStuff={isShowingStuff} setIsShowingStuff={this.setIsShowingStuff}/>
  }
}

Ok, but what if we want to share the logic contained in MySmartComponentwith other dumb components? You write a Higher Order Component.

import React, { Component} from 'react';

const MyDumbComponent = ({ isShowingStuff, setIsShowingStuff }) => (
    <div>
        <button onClick={() => setIsShowingStuff(!isShowingStuff)}> Click me </button>
        <span> Some stuff </span>
        {isShowingStuff && <span> More stuff </span>}
        <span> Even some more stuff </span>
    <div>
)
// A HOC is a function that returns a component definition.
const withIsShowingStuff = (ComponentType) => class SmartComponent extends Component {
  state = {
    isShowingStuff: false,
  }
  
  setIsShowingStuff = (isShowing) => this.setState({ isShowingStuff: isShowing})
  
  render() {
    const { isShowingStuff } = this.state;
    return <ComponentType  isShowingStuff={isShowingStuff} setIsShowingStuff={this.setIsShowingStuff}/>
  }
}

// Cool now we can apply it
const MySmartComponent = withIsShowingStuff(MyDumbComponent);

That is cool, but recompose takes it a step further and provides a toolbelt to create HOCs. With recompose you can do the above in fewer lines of code.

import React, { Component} from 'react';
import { withState } from 'recompose';

const MyDumbComponent = ({ isShowingStuff, setIsShowingStuff }) => (
    <div>
        <button onClick={() => setIsShowingStuff(!isShowingStuff)}> Click me </button>
        <span> Some stuff </span>
        {isShowingStuff && <span> More stuff </span>}
        <span> Even some more stuff </span>
    <div>
)

const withIsShowingStuff = withState('isShowingStuff', 'setIsShowingStuff', false);
const MySmartComponent = withIsShowingStuff(MyDumbComponent);

Recompose provides more utils than withState but these examples capture the gist of it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment