Use a React Portal to design an API for a global layout component
We have all been there. We are gradually building a large scale application, and the header on each page looks like this:
And then, at some point, someone thinks: Oh, now on this page only, it makes total sense to use this beautiful space top right for some controls:
Of course, UX-wise it makes sense, but code-wise this can be a nightmare to implement. Some options we have:
- Use a switch case in the global Header to render something there based on the current page
- Use CSS to visually squeeze it into the Header, but code-wise it remains in the current page implementation
- Use a Portal
For us, after some discussion, we came to the conclusion, that a Portal makes perfect sense here. The main benefit for us was, that the code, which goes into the Header, can be co-located with the current page implementation.
The implementation itself was fairly straightforward.
- First we added a LayoutProvider. The Provider is designed to store the slot Element of the Header. And also a setter for that.
- Then in the Header, we set the Element with a ref on the respective node.
- Lastly, we wrote the Portal itself. If the Element has been set, we render the Portals children into that.
Eventually everywhere in our code, where content should be added to the Header, we are able to simply use the Portal and render what we need as its children.
Here is a Codesandbox with an exemplary implementation. This is strongly influenced by this great article by Jenna Smith from the Radix UI team. Thanks for your inspiring work!