Six Common Patterns for Building Solid Components and Features with ReactJS (1/3)

JavaScript is a vast world. Especially when you are starting out, it may be hard to find a consistent pattern of coding. This is because in the “World of JS” many different paths achieve the same result.

“React Land” does not cover quite as much ground, but shares similar challenges. For this reason, I would like to share some of the strategies and patterns I normally follow to write clear and cohesive components.

Concepts in this series:
1. Stateless Functional Components (part 1)
2. Hybrid (Controlled or Uncontrolled) Components (part 1) 
3. Compound Components by Extending Children (part 1)

Stay tuned! Future posts in this series will cover:
4. Component Communication with Context (part 2)
5. Global State with Redux (part 2)
6. Render Props vs Higher Order Components (part 3)


Stateless Functional Components

The pattern

This pattern behaves as a snapshot of your UI depending on the props being passed down — in other words it’s just a function.

Possible uses

Good to use for: dumb components (which don’t need any state or React lifecycle hooks) or a component that only cares about wrapping its children (which makes it behave as a placeholder).

👍 Pros

  • No class declaration, simpler code
  • No need for this keyword
  • Works with React Context

👎 Cons

  • You can’t have any React lifecycles hooks.
  • You cannot set a ref on a stateless functional component. 
    This will fail: <Component ref={(r) => console.log(r)} />

Example

<Footer /> Placeholder

Code

Stateless Component

Hybrid (Controlled or Uncontrolled) Components

The pattern

This pattern relies on distinguishing between default props and controllable props, which are passed down to the Component.

The component then decides if it should be Controlled or if it should switch to it’s internal state and behave as an Uncontrolled component.

Uncontrolled === use internal state to render the component
 Controlled === use props to control the component

Tip: Passing props to a component doesn’t automatically convert it to a controlled component. For example, you can pass props to define the initial state of a component ex:<Component defaultVisible={false} /> and from that point forward you will use the internal state to update the component.

Possible uses

When the component may need to manage its own state (uncontrolled component) while also providing the flexibility of being controlled by the developer (controlled component).

👍 Pros

  • Gives flexibility to the developer
  • This pattern can be composed easily to add extra functionality

👎 Cons

  • Extra work — it needs to handle props and the internal state
  • More complexity — if a component has multiple props, you have to check each prop and determine if it should behave as controlled or uncontrolled

Tip: Never try to sync the props with the inner state of the component (only use them to initialize the state). It is difficult and can open the door to unexpected bugs 🐛. Instead, use the props directly or ignore them and rely on the inner state.

Tip: Even if more work is required, I prefer to check each property separately and decide if the component’s behaviour should be controlled or uncontrolled. This creates a better DX (developer experience).

Example

Simple toggle working as a hybrid component

Hybrid Component UI

Code

Collapsible Hybrid Component implementation

Compound Components by Extending Children

The pattern

This pattern focuses on passing down the state of the parent component to its children. This solves the problem that arises when a child component wants to communicate with its parent.

Possible uses

This pattern works well in situations where you want to have communication between a parent component and its children.

👍 Pros

  • Utilizes a basic Javascript feature to pass down a slice of the parent state or a callback function

👎 Cons

  • Requires you to enforce a fixed JSX structure for its children so the parent can correctly extend its children:
Explanation of fixed JSX structure

Example

Simple form extending their children with isDisabled property

Code


What’s next?

Keep reading about more React patterns in the sequel to this post, coming soon!