Back to the blog

14 React patterns every React developer should know

author image

Manoj Kumar Patra

Technology | May 29, 2019

hero image

1. Functional component

Functional components are stateless reusable components whose first argument props is an object which contains all inputs to the component in the form of key-value pairs.

We can do type-checking of inputs with PropTypes which is from the package prop-types.

Optionally, we can use defaultProps to set default values for any inputs to the component.

function Greeting(props) {
  return <div>Hi {props.name}!</div>;
}

Greeting.defaultProps = {
  name: "Guest"
};

2. Destructuring props

Instead of using every input inside the component as props.<input>, we can directly use the input with destructuring.

function Greeting({ name }) {
  return <div>Hi {name}!</div>;
}

Greeting.defaultProps = {
  name: "Guest"
};

3. JSX Spread attributes

Sometimes we may want to use one of the inputs in the component and pass the remaining inputs to any child component. This is where we can make use of the rest parameter syntax.

This strategy is most popular in forwarding DOM props to components.

function Greeting({ name, ...restProps }) {
  return <div {...restProps}>Hi {name}!</div>;
}

Greeting.defaultProps = {
  name: "Guest"
};

4. Merging destructured props with other values

One case where might need merging props with other values is trying to pass in class names as inputs to a component which has another class already applied to it.

function Greeting({ name, className, ...restProps }) {
  return (
    <div
      {...restProps}
      className={['btn', className].join(" ")}
    >
      Hi {name}!
    </div>
  );
}

Greeting.defaultProps = {
  name: "Guest"
};

5. Conditional rendering

if

condition && <Component />

unless

condition || <Component />

if-else

condition
? (
  <Component1 />
)
: (
  <Component2 />
)

6. Children Types

React can render children from most types including an array or a string.

// String
<div>Hello World!</div>

// Array
<div>{["Hello ", <span>World</span>, "!"]}</div>

7. Array as children

An array along with the map() function can be used to render a collection of elements inside another React component.

<ul>
  {["Jane", "Mike"].map(name => (
    <li>{name}</li>
  ))}
</ul>

8. Children pass-through

To create a component to apply context and render its children, we can simply return the following from the component:

return React.Children.only(this.props.children);

9. Proxy component

One common use will be to create a custom button component and avoid writing common button attributes such as the type attribute hundreds of times.

const Button = props => <button type="button" {...props} />

10. Style component

A proxy component applied to the practices of styles.

Say we want to create buttons for different cases such as primary, error, etc.

Instead of creating multiple such components, we can create one single component as shown below:

const Btn = ({ className, primary=false, error=false, ...props }) => (
  <button
    type="button"
    className={classnames("btn", primary && "btn-primary", error && "btn-danger", className)}
    {...props}
  />
);

Now we can create one component each for the primary button and danger button as follows:

const PrimaryBtn = props => <Btn {...props} primary />;
const DangerBtn = props => <Btn {...props} error />;

11. Layout component

Layout component can be used for layout purposes. So, basically, it acts as a static DOM element and hence, we can stop making frequent updates to this component by returning false from the shouldComponentUpdate() function.

12. Container component

A container component can be used for fetching the data, connecting to redux store, dispatching actions and rendering its corresponding sub-components.

13. Higher-order component

A higher-order component takes and/or returns a component. Here is an example:

const Greeting = ({ name }) => {
  if (!name) {
    return <div>Connecting...</div>;
  }

  return <div>Hi {name}!</div>;
};
const Connect = ComposedComponent =>
  class extends React.Component {
    constructor() {
      super();
      this.state = { name: "" };
    }

    componentDidMount() {
      this.setState({ name: "Michael" });
    }

    render() {
      return <ComposedComponent {...this.props} name={this.state.name} />;
    }
  };
const ConnectedMyComponent = Connect(Greeting);

This pattern can be used for fetching and providing data to any number of functional components.

14. State hoisting

State hoisting is possible by passing a callback from a container component to a child component. So, this way we can update the container component from an event in the child component.

A common example is of a controlled input.

class ControlledNameInput extends React.Component {
  constructor() {
    super();
    this.state = { name: "" };
  }

  render() {
    return (
      <input 
        type="text" 
        value={this.state.name} 
        onChange ={e => this.setState({ name: e.target.value })}
      />
    );
  }
}
Browse all categories