Pure Components, Interfaces and Logic Hooks.

This architecture is divisible into three components, Pure Components, Interfaces and Logic Hooks. It is a variant on the Presentational and Container Components pattern described by Dan Abramov, now considering the existence of Hooks.

Pure Component
Pure Component
Interface
Logic Hook

Interfaces are mainly concerned with how information should be shared between Logic Hooks and with Pure Components. Interfaces receive functions and values provided by Logic Hooks and share them with other Logic Hooks or pass them as props to Pure Components.

Logic Hooks are similar to Container Components. Pure Components are similar to Presentational Components. But they differ on some points.

Comparison

* Presentational Components and Pure Components

From Dan’s post:

My presentational components:

  • Are concerned with how things look.
  • May contain both presentational and container components** inside, and usually have some DOM markup and styles of their own.
  • Often allow containment via this.props.children.
  • Have no dependencies on the rest of the app, such as Flux actions or stores.
  • Don’t specify how the data is loaded or mutated.
  • Receive data and callbacks exclusively via props.
  • Rarely have their own state (when they do, it’s UI state rather than data).
  • Are written as functional components unless they need state, lifecycle hooks, or performance optimizations.
  • Examples: Page, Sidebar, Story, UserInfo, List.

My Pure Components:

  • Same (“Are concerned with how things look.”).
  • May contain other Pure Components, markup, and styles.
  • Same (“Often allow containment via this.props.children.”) *props.children*.
  • Same (“Have no dependencies on the rest of the app, such as Flux actions or stores.”).
  • Same (“Don’t specify how the data is loaded or mutated.”).
  • Same (“Receive data and callbacks exclusively via props.”).
  • Don’t have their own state. They should receive, as props, a local state provided by a Logic Hook through an Interface.
  • Are written as functional components.
  • Same (“Examples: Page, Sidebar, Story, UserInfo, List.”).

* Container Components and Logic Hooks

From Dan’s post:

My container components:

  • Are concerned with how things work.
  • May contain both presentational and container components** inside but usually don’t have any DOM markup of their own except for some wrapping divs, and never have any styles.
  • Provide the data and behavior to presentational or other container components.
  • Call Flux actions and provide these as callbacks to the presentational components.
  • Are often stateful, as they tend to serve as data sources.
  • Are usually generated using higher order components such as connect()from React Redux, createContainer() from Relay, or Container.create()from Flux Utils, rather than written by hand.
  • Examples: UserPage, FollowersSidebar, StoryContainer, FollowedUserList.

My Logic Hooks:

  • Same (“Are concerned with how things work.”).
  • Shouldn’t contain other components, markup or styles.
  • Provide the data and behavior to Interfaces.
  • Call Flux actions and provide these as callbacks to Interfaces.
  • Same (“Are often stateful, as they tend to serve as data sources.”).
  • n/a (“Are usually generated using higher order components such as connect()…”).
  • Examples: useUser, useFollowers, useStory, useFollowed.

Just like the Presentational and Container Component pattern, this separation makes it easier to replace or delete code. If you wanted to replace your state container, you would need to update your Logic Hooks, but not your Interfaces or Pure Components. But it is particularly useful if your application has different UI flows, hence the name “Interface”. For example, you could use the same Logic Hooks for a React and React Native application with different Interfaces. These Interfaces would receive information from the same Logic Hooks, and accommodate Pure Components in distinct ways.

Full example

Todo-list example