Change body class in React app components

Manipulating the body class attribute in react app’s is not straight forward, because of it’s nested components architecture. The workaround demonstrated in this article helps out.

A possible solution for changing the body-tag’s class attribute is manipulating document.body.class value directly in componentDidMount and componentDidUnmount. The drawback of using react’s lifecycle hooks is, they’re not available in function components. Also it’s a quite repetitive task.

A better solution is using the module react-side-effect to create a component that set’s the class value.

The core of this component is the withSideEffect HoC:

withSideEffect(
  reducePropsToState,
  handleStateChangeOnClient
)(BodyCssClass)

The withSideEffect higher-order-component, calls reducePropsToState with props of each mounted instance when mounting, unmounting or receiving new props. We return some state aggregated from these props and handleStateChangeOnClient is called with this state. The latter function just manipulates the DOM element document.body.class

Full code of the component:

import { Component, Children } from 'react';
import PropTypes from 'prop-types';
import withSideEffect from 'react-side-effect';

// cssClass attribute is given the css class to be added to the body tag
class BodyCssClass extends Component {
  render() {
    return this.props.children || null;
  }
}

BodyCssClass.propTypes = {
  cssClass: PropTypes.string.isRequired
};

// reducePropsToState is called with props of each mounted instance
const reducePropsToState = (propsList) => {
  let bodyCssClass = '';
  propsList.forEach(function (props) {
    bodyCssClass = props.cssClass;
  });
  return bodyCssClass;
};

const handleStateChangeOnClient = (className) => {
  document.body.className = className
};

export default withSideEffect(
  reducePropsToState,
  handleStateChangeOnClient
)(BodyCssClass);

A create-react-app working demo example is available on https://github.com/lujakob/react-example-body-class

Also react-helmet is a very good option that provides additional possibilities for manipulating “head” tags from within components.