Glad Chinda Full-stack web developer learning new hacks one day at a time. Web technology enthusiast. Hacking stuffs @theflutterwave.

A complete guide to default props in React

7 min read 2093


Learn all you need to know about setting default props for different flavors of React components.

React is a very powerful component-based JavaScript framework for building scalable applications that can run on different platforms — server, web, mobile, desktop, etc. Thousands of applications running on these platforms today are built on top of React.

Some of the amazing features of React include: lean framework, virtual DOM, JSX support, code reusability. You can learn more about React from this documentation.

This guide, at a very basic level, attempts to expose all you need to know about setting default props for React components. It is mainly meant for newbies to the React framework. Hence, it requires some elementary knowledge of React.

However, it is very possible that a developer, who has been using React for quite some time now, may still find some parts of this guide insightful.

The screenshots in this guide show views that are rendered with some basic Bootstrap 4 CSS styling. To get very similar results, you will have to run the code snippets with some additional Bootstrap styles.

Hello, React component

React apps are usually a composition of several independent components that make up the UI of the application. React components are the building blocks of any React application.

A React component is simply a JavaScript function that takes an object of arbitrary inputs known as props and returns React elements describing what should be rendered on the UI.

// Simple React Component
function ReactHeader(props) {
  return <h1>React {props.version} Documentation</h1>
}

This code snippet defines a very simple ReactHeader component that renders a <h1> element containing a heading for the documentation of a specified React version. It uses the JSX (JavaScript XML) syntax for creating the DOM elements hierarchy of the component in a declarative way. You can learn more about using JSX with React here.

Without JSX, the previous code snippet will be written like this:

// Simple React Component (without JSX)
function ReactHeader(props) {
  return React.createElement('h1', null, `React ${props.version} Documentation`);
}

JSX is not required for you to use React. For example, if you intend to use React without any form of compilation, then JSX wouldn’t be the way to go.

In fact, every JSX in your React component gets compiled to its createElement equivalent before the component is rendered. However, in this guide, JSX will be used in all code snippets where possible.

From the previous code snippets, it is pretty clear that the ReactHeader component requires that a version prop is passed to it.

The ReactHeader component can be rendered on the DOM (inside an arbitrary element) as follows:

// Render a React Component
ReactDOM.render(, document.getElementById('root'));

Notice here that the ReactHeader has been rendered with the version prop set to 16. At the moment, everything seems to be working properly in the ReactHeader component as shown in the following screenshot.

ReactHeader Component

Default props

What happens when the version prop is not passed?

// Render the ReactHeader Component
ReactDOM.render(, document.getElementById('root'));
ReactHeader Component without version

You probably might have guessed right. Here is what happens when the ReactHeader component is rendered without the version prop:

Since the version prop is not passed, the reference to props.version in the component is undefined, hence the above screenshot.

One way you could handle this is by applying conditional rendering. You can prevent the component from rendering whenever a required prop is not passed or is invalid and render nothing instead, as shown in the following snippet:

// Simple React Component
function ReactHeader(props) {
  return (
    Number.isFinite(props.version)
      ? <h1>React {props.version} Documentation</h1>
      : null
  );
}

Another way you could fix this is by setting default props for the component. You can tweak the component a bit to use a default value for the version prop whenever it is not passed.

Here it is:

// With JSX
function ReactHeader(props) {
  return <h1>React {props.version || 16} Documentation</h1>
}

// OR
// Without JSX
function ReactHeader(props) {
  return React.createElement('h1', null, `React ${props.version || 16} Documentation`);
}

Here, the logical OR (||) operator is used to set a fallback value for the version prop whenever it is not passed. A default value of 16 has been set for the version prop. With this change, everything now works as expected.

In this guide, you will be exposed to different ways of setting default props for different flavors of React components:

  1. Using React.createClass() API

  2. Class Components

  3. Functional Components

  4. Using Higher-Order Components

React.createClass()

In React, classes are best suited for building stateful components, in which you need to maintain state internally within the component, or in cases where you want to leverage on the lifecycle methods of the component.

When React was released initially, classes have not really become a thing in JavaScript. Hence, there was actually no way of creating classes in JavaScript.

However, React provided with the React.createClass() API for creating class-like components. Over time, this API was deprecated and finally removed from React in favor of ES6 classes.

If you are using a React version prior to 15.5.0, then you can use the React.createClass() API to create a simple React component as follows:

import React from 'react';

/**
 * ThemedButton Component
 * Using React.createClass()
 *
 * Renders a Bootstrap themed button element.
 */
 
const ThemedButton = React.createClass({

  // Component display name
  displayName: 'ThemedButton',
  
  // render() method
  render() {
    const { theme, label, ...props } = this.props;
    return { label }
  }
  
});

This code snippet creates a very simplistic ThemedButton component using the React.createClass() API. This component basically renders a Bootstrap themed button based on the props passed to it.

Also, notice that it requires a theme prop and a label prop to be passed for it to properly render the button.

A set of themed buttons can now be rendered on the React app as follows:

import React from 'react';
import ReactDOM from 'react-dom';

// [...ThemedButton component here]

function App(props) {
  return (
    <div>
      <ThemedButton theme="danger" label="Delete Item" />
      <ThemedButton theme="primary" label="Create Item" />
      <ThemedButton theme="success" label="Update Item" />
      <ThemedButton theme="warning" label="Add to Cart" />
      <ThemedButton />
    </div>
  );
}

const rootElement = document.getElementById('root');
ReactDOM.render(<App />, rootElement);

Notice here that the ThemedButton component has been rendered five times in the app. At the fifth time, the ThemedButton isn’t passed any props. Here is a screenshot of what the app looks like:

ThemedButton App

From the above screenshot, you will notice that the fifth button isn’t visually represented on the view since it is rendered without theme and label props. Hence, there is need to set default props for the ThemedButton component.

For components created using the React.createClass() API, you can set default props by adding a method named getDefaultProps to the object literal.

The getDefaultProps() method should return an object representing the default props set for the component. Here it is:

const ThemedButton = React.createClass({

  // Component display name
  displayName: 'ThemedButton',
  
  // render() method
  render() {
    const { theme, label, ...props } = this.props;
    return <button className={`btn btn-${theme}`} {...props}>{ label }</button>
  },
  
  // Set default props
  getDefaultProps() {
    return {
      theme: "secondary",
      label: "Button Text"
    };
  }
  
})

In this snippet, default props have been set for the ThemedButton component. The theme prop defaults to “secondary” if not passed, while the label prop defaults to “Button Text”.

With the default props set, the app should now look like the following screenshot:

ThemedButton with Default Props

Class components

In more recent versions of React, class components can be created by leveraging on the ES6 class syntax. This is what the ThemedButton component will look like using the ES6 class syntax.

import React, { Component } from 'react';

class ThemedButton extends Component {

  // render() method
  render() {
    const { theme, label, ...props } = this.props;
    return <button className={`btn btn-${theme}`} {...props}>{ label }</button>
  }

}

For a React component created using the ES6 class syntax, you can set default props by adding a static property named defaultProps to the component class.

The defaultProps static property should be set to an object representing the default props for the component.

This can be done by defining defaultProps on the component class itself, outside of the class body, as shown in the following code snippet:

class ThemedButton extends React.Component {
  render() {
    // ...implement render method
  }
}

// Set default props
ThemedButton.defaultProps = {
  theme: "secondary",
  label: "Button Text"
};

With the addition of static class properties and methods to the ECMAScript specification, you can alternatively specify the defaultProps as shown in the following snippet:

class ThemedButton extends React.Component {
  render() {
    // ...implement render method
  }
  
  // Set default props
  static defaultProps = {
    theme: "secondary",
    label: "Button Text"
  }
}

Functional components

In React, the function syntax is appropriate for components that simply render elements without keeping track of their state or lifecycle. These components are usually called functional components or stateless functional components.

Here is what the ThemedButton component will look like when re-written as a stateless functional component:

import React from 'react';

function ThemedButton(props) {
  const { theme, label, ...restProps } = props;
  return <button className={`btn btn-${theme}`} {...restProps}>{ label }</button>
}

As with class components, you can set default props on a functional component by adding a static property named defaultProps to the component function itself.

function ThemedButton(props) {
  // ...render component
}

// Set default props
ThemedButton.defaultProps = {
  theme: "secondary",
  label: "Button Text"
};

Alternatively, with the ES6 object destructuring syntax, you can destructure the props of a functional component with default values. You can learn more about ES6 destructuring from this article.

Here is what the ThemedButton component will look like with destructured props:

import React from 'react';

// METHOD 1:
// Default Props with destructuring
function ThemedButton(props) {
  const { theme = 'secondary', label = 'Button Text', ...restProps } = props;
  return <button className={`btn btn-${theme}`} {...restProps}>{ label }</button>
}

// METHOD 2:
// More compact destructured props
function ThemedButton({ theme = 'secondary', label = 'Button Text', ...restProps }) {
  return <button className={`btn btn-${theme}`} {...restProps}>{ label }</button>
}

Using higher-order components

In React, a higher-order component (HOC) is basically a function that takes a React component as its argument and returns another React component, usually an enhancement of the original.

Higher-order components are very useful for component composition and there are a lot of packages that provide higher-order components that can be used with React components — a very popular one being recompose.

Recompose is a rich collection of higher-order components that can be used with React components. It is more like Lodash for React. You can learn more about the higher-order components and API provided by recompose in this reference.

You can run the following command to install recompose as a dependency for your project:

npm install recompose --save

Recompose exports a defaultProps function that returns a higher-order component which sets the specified default props on any React component passed to it and returns the modified React component.

Here is how the ThemedButton component can be re-written using the defaultProps higher-order component from recompose.

import React from 'react';
import { defaultProps } from 'recompose';

// React Component
function ThemedButton(props) {
  const { theme, label, ...restProps } = props;
  return <button className={`btn btn-${theme}`} {...restProps}>{ label }</button>
}

// Default Props HOC
const withDefaultProps = defaultProps({
  theme: "secondary",
  label: "Button Text"
});

// Enhanced Component with default props
ThemedButton = withDefaultProps(ThemedButton);

Conclusion

Using default props can bring about great improvements to your React components. In this guide, you have been exposed to several ways in which you can set default props for different flavors of React components you might have in your React application.

Clap & Follow

If you found this article insightful, feel free to give some rounds of applause if you don’t mind.

You can also follow me on Medium (Glad Chinda) for more insightful articles you may find helpful. You can also follow me on Twitter (@gladchinda).


Plug: LogRocket, a DVR for web apps

https://logrocket.com/signup/

LogRocket is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single page apps.

Try it for free.

Glad Chinda Full-stack web developer learning new hacks one day at a time. Web technology enthusiast. Hacking stuffs @theflutterwave.

Leave a Reply