Rendering a React Application Across Multiple Containers
Tags: javascript, react
Published: 2019-11-22 23:56:33

---
title: Rendering a React Application Across Multiple Containers
published: true
date: 2019-10-14 00:00:00 UTC
tags: Javascript,React
canonical_url: http://www.petecorey.com/blog/2019/10/14/rendering-a-react-application-across-multiple-containers/
---

A few of my recent articles have been embedding limited builds of [Glorious Voice Leader](https://www.gloriousvoiceleader.com/) directly into the page. At first, this presented an interesting challenge. How could I render a single React application across multiple container nodes, while maintaining shared state between all of them?

While the solution I came up with probably isn’t _best practice_, it works!

As a quick example, imagine you have a simple React component that manages a single piece of state. The user can change that state by pressing one of two buttons:

```

const App = () => {
  let [value, setValue] = useState("foo");
  return (
    <div>
      <button onClick={() => setValue("foo")}>
        Value is "{value}". Click to change to "foo"!
      </button>
      <button onClick={() => setValue("bar")}>
        Value is "{value}". Click to change to "bar"!
      </button>
    </div>
  );
};

```

Normally, we’d render our `App` component into a container in the DOM using `ReactDOM.render`:

```

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

```

But what if we want to render our buttons in two different `div` elements, spread across the page? Obviously, we could build out two different components, one for each button, and render these components in two different DOM containers:

```

const Foo = () => {
  let [value, setValue] = useState("foo");
  return (
    <button onClick={() => setValue("foo")}>
      Value is "{value}". Click to change to "foo"!
    </button>
  );
};

const Bar = () => {
  let [value, setValue] = useState("foo");
  return (
    <button onClick={() => setValue("bar")}>
      Value is "{value}". Click to change to "bar"!
    </button>
  );
};

ReactDOM.render(<Foo />, document.getElementById('foo'));
ReactDOM.render(<Bar />, document.getElementById('bar'));

```

But this solution has a problem. Our `Foo` and `Bar` components maintain their own versions of `value`, so a change in one component won’t affect the other.

Amazingly, it turns out that we can create an `App` component which maintains our shared state, render that component into our `#root` container, and within `App` we can make additional calls to `ReactDOM.render` to render our `Foo` and `Bar` components. When we call `ReactDOM.render` we can pass down our state value and setters for later use in `Foo` and `Bar`:

```

const App = () => {
  let [value, setValue] = useState("foo");
  return (
    <>
      {ReactDOM.render(
        <Foo value={value} setValue={setValue} />,
        document.getElementById("foo")
      )}
      {ReactDOM.render(
        <Bar value={value} setValue={setValue} />,
        document.getElementById("bar")
      )}
    </>
  );
};

```

Our `Foo` and `Bar` components can now use the `value` and `setValue` props provided to them instead of maintaining their own isolated state:

```

const Foo = ({ value, setValue }) => {
  return (
    <button onClick={() => setValue("foo")}>
      Value is "{value}". Click to change to "foo"!
    </button>
  );
};

const Bar = ({ value, setValue }) => {
  return (
    <button onClick={() => setValue("bar")}>
      Value is "{value}". Click to change to "bar"!
    </button>
  );
};

```

And everything works! Our `App` is “rendered” to our `#root` DOM element, though nothing actually appears there, and our `Foo` and `Bar` components are rendered into `#foo` and `#bar` respectively.

Honestly, I’m amazed this works at all. I can’t imagine this is an intended use case of React, but the fact that it’s still a possibility made my life much easier.

Happy hacking.