Improve how you style and compose React apps — Use components in defaultProps

Theming guidelines — Part 5 — How to solve the problem with components with a large number of props

I want to introduce you a technique called components in defaultProps. This technique will allow you to change every aspect of your components and make them ultimately reusable 🤯.

Photo by Katya Austin on Unsplash

You can read about the categorization of React components in the previous article.

React functional components are simple functions modern javascript allow us to use default function parameters together with object destructuring assignment.

function withDefaultObjectParamemeterAndDestructuring({
a = 1,
b = 2,
} = {}) {
console.log(`a=${a}, b=${b}`);
}
withDefaultObjectParamemeterAndDestructuring({b: 5}); // "a=1, b=5"
with = {} function can be called without argument fn() and you do not have to add unessesary empty object fn({})

If you want to know more about function parameters and the problem when the function takes more parameters the have a look at the part of the recent article from course I have prepared.

📚 Define some vocabulary

JSX may remind you of a template language, but it comes with the full power of JavaScript. JSX produces React “elements”. JSX In Depth

An element is a plain object describing what you want to appear on the screen in terms of the DOM nodes or other components. Elements can contain other elements in their props. Creating a React element is cheap. Once an element is created, it is never mutated.

React.Component

A component can be declared in several different ways. It can be a class with a render() method. Alternatively, in simple cases, it can be defined as a function. In either case, it takes props as an input and returns an element tree as the output.

Class Properties
A defaultProps can be defined as a property on the component class itself, to set the default props for the class. This is used for undefined props, but not for null props.

Instance Properties
Props (which stands for properties) are commonly used terms for component object input argument. This is why people say that the props flow one way to React from parents to children.

The state contains data specific to the component that may change over time. The state is user-defined, and it should be a plain JavaScript object.

Problem with components with a large number of props

The dealing with component compositions can inflate the number of props if you want to allow customizations of nested components.

Most common reasons for an increased number of props

  • grouping many components and providing customizations via props them in the parent component
  • providing customizable className for every nested component and for hover focus or other pseudo selectors
  • providing customizable handler function to nested components
  • providing customizable translations to the nested components

The Solution

tl;dr using render props function and declaring nested components as defaultProps using any CSS in JS library

Why are defaultProps better than default function parameters

You can not get the value from default function parameters outside of the function closure. The defaultProps is a static property you can get its value without creating an instance.

const Component = ({a = 1}) => {}
Component.defaultProps = {b: 2}
Component.a // Error // variable "a" is not accesible
Component.defaultProps.b // 2

Customizations of nested components are endless. You can get any value from defaultProps and extend it and provide update value to using props. Value can be a component and you can extend it using CSS in JS library.

With the benefits of defaultProps over default function parameters, I would recommend to only use defaultProps for components.

Render props or Function as Child pattern

The term “render prop” refers to a technique for sharing code between React components using a function as a children prop.

📖 https://reactjs.org/docs/render-props.html
The simplest example of render props
React you know

Do not use standard CSS for React Components

The are many discussions about the pros and cons of CSS in JS.

👎 A standard way of adding CSS to the web page is to load all styles in one file in the head. You will over fetch styles and most of the web pages are using only 2–3% of loaded styles.

👎 A standard CSS is adding all styles into a global namespace open to class name collisions

👎 Overriding styles is unstable since you need to add updated style in later in a file or with a more specific selector. The CSS preprocessor build can mix the order of the files and your styles will be different

👎 …

The global nature of CSS is requiring us to test every change manually, and we are not certain what can break in a large application.

The Next Generation of CSS-in-JS

Emotion logo

Emotion is a performant and flexible CSS-in-JS library. Building on many other CSS-in-JS libraries, it allows you to style apps quickly with string or object styles. It has predictable composition to avoid specificity issues with CSS. With source maps and labels, Emotion has a great developer experience and great performance with heavy caching in production.

👍 styles will be colocated with component
👍 unique classNames are generated and managed by the library
👍 you are loading only styles that are used on the page
👍 automatic vendor auto-prefixing
👍 all the options from CSS preprocessors like nested selectors, variables, pseudoselectors

Using a presentational component in defaultProps of presentational containers

The power of components in default props enormous. Styled components that know nothing about the model of the application can be used by containers that know about the data model. It makes the UI highly reusable.