React gives us a great component abstraction. Each of these components represents a node in the DOM. Each component is self contained, doesn’t talk up the component hierarchy directly and passes explicit data and code down the hierarchy. But what about when you have a React app that wants to reach out and modify something it doesn’t control?
A Couple Use Cases
There are potentially a few use cases for this. For instance, modals that need to render outside your application’s potentially
position: relative containers. Or, as we’ll see below, your app wants to modify the
body tag in your html document.
The most common reason I’ve found for messing with the body tag is to provide some style attribute. It’s not uncommon to have full-page style differences between pages in our apps. If you have a “single page” js app in the browser, you need to be able to modify the body tag in code.
Let’s use an example where on some pages in your app, the theme is “dark”, where the body background color should be black. On other pages, the entire body background color should be the default white. We’ll make a component that lives high in the hierarchy and takes an
isDark property to determine if the rendered page is dark or light.
Body is Outside Your React App
You can’t mount your React app directly on
document.body, at least without warnings. This is considered bad practice, because other scripts or browser plugins often modify the document body directly. So you’ll have to reach out of your React app and modify the body directly.
Tie Into the React Lifecycle
First, you just need a point in time in your app’s lifecycle where you know you want to modify the
body class. React has a bunch of lifecycle hooks that will come in handy. A great early-lifecycle hook for modifying the DOM is
componentDidMount. Usually, we would be accessing DOM nodes that are children of our Component. Again, in this case, we’re reaching out beyond where a React component usually should. The usual
React.findDOMNode functions will not be needed, because React isn’t managing the body node. Instead, we’ll just use the
document.body api directly.
With these two bits in hand, you have the pieces necessary for your body-modifying component:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
To use, pass an
isDark attribute to activate the
darkClass class on the body tag:
1 2 3
Are there any other ways you’ve found to reach out of React and modify the DOM directly. What have been your use cases?