Skip to content

Instantly share code, notes, and snippets.

@mathieu-anderson
Last active February 12, 2019 13:18
Show Gist options
  • Save mathieu-anderson/59734f2cf9692b392a8b460a022adefd to your computer and use it in GitHub Desktop.
Save mathieu-anderson/59734f2cf9692b392a8b460a022adefd to your computer and use it in GitHub Desktop.

!! Disclaimer : no value judgement !! !! Disclaimer : I'm not an expert !!

Components are the building block of a React app. There have been historically many ways of defining a component. But there are two main approach :

  • class component
  • "stateless functional components", or more simple functional component (the "stateless" part is going away soon)

Difference between class and functional components

  • class :

  • functional :

    • has props
    • pure function (the same input always return the same result)
      • props in => markup out. Ideal for design elements.
    • tend to be smaller
    • extremely easy to compose (higher order components, render props) and unit-test

In our codebase :

  • almost 100% classes
  • big components with complex behaviours baked in, a lot to read, not the most easy to navigate (back and forth between multiple render methods and state management)
  • Aside : we use Redux. The ability to connect component to a central immutable state, encourages the use of functional components (because you don't need internal state if you can pass it as props)
  • In a perfect world the only internal state we would need would be UI state (typically show/hide), all data state handled by Redux

How FC help me (and us):

  • Objective : write less code, make less mistakes, make PRs easier to read and review, make your code more reusable / maintainable.
  • Added bonus : thinking a bit more about the why before the how
  • Before starting to build something new / extend something old :
    • does it need data from an external source (side effect) ?
      • no : functional
      • yes :
    • will it change? (i.e. does it need lifecycle methods / event handlers)
      • no : functional
      • yes : class

An example of refactoring : SubMenu.tsx

  • initial situation :

    • Introduction of TetheredList remove the need for state management in SubMenu
    • Becomes therefore a pure UI component (data in, markup out)
    • Markup generated through a chain of renderXXX methods : renderMenuItems -> renderMenuItem -> renderModalLink / renderExportButton / renderNavLink -> markup
  • working with it / coming in with fresh eyes :

    • verbose (class syntax)
    • hard to navigate (bouncing between class methods)
    • unclear where the main render is happening
    • unclear what is rendered when (vague-ish typings)
  • objective :

    • breaking off the render methods of Submenu.tsx as their own components (they are basically already FCs)
    • refactor Submenu.tsx itself as an FC rendering SubmenuItem FCs based on the props it is passed.
    • clarify the flow : Submenu(SubmenuItems[]) => Submenu UI
  • result :

    • no more state management in a component that is not directly concerned with it (TetheredList has it)
    • smaller units of information
    • clearer responsability for each of these units
    • clearer typing (precisely type each kind of SubmenuItem)
    • hopefully easier to add new types of Submenu items

Takeaway :

  • FC allows us to have clearer repsonsablilities for each of our components
  • Separating concerns rule of thumb:
    • business / data logic : state -> class
    • presentation logic : props -> function
  • In case you don't know this article : https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0 !! read cautiously as loose guideline (not strict rules), also a little dated !!
  • Coming soon : hooks. Arguably no reason to use classes any more: https://medium.com/@dan_abramov/making-sense-of-react-hooks-fdbde8803889. Additive! No need to refactor everything (or anything). The objective is to have only one way of defining components, and functions are it for the React team. No need to panic though, strong backwards compatibility philosophy, classes will not be removed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment