Cover

December 10, 2020

Speed up your web development time by integrating Webflow into a React application

Writing JSX to build pixel perfect UI elements can be very time consuming and frustrating. Learn how react engineers can inject complex elements / React components into a Webflow generated HTML page.

author
By Rishabh PoddarCo-Founder and CTO at SuperTokens

Writing JSX to build pixel perfect UI elements can be very time consuming and frustrating. I’m talking about the process of figuring out the exact padding, margin, flexbox, width, height etc to match the required design spec. As React engineers, our time is most well spent on what we can do uniquely - write state management logic, API calls, error handling, component architecture, animations and building complex components that require lots of user interactions.

The aim of this blog post is to provide a methodology using which designers can build the simpler UI HTML elements using Webflow and React engineers can inject complex elements / React components into the generated HTML page. This works best for sites that have less user specific / user generated content - like several b2b sites.

Note: For those who do not know about Webflow, it’s a tool that let’s designers design the UI, and it emits fully functional HTML code.

Technical guide

As an example, let’s consider a webpage where most of the body is generated using Webflow apart from the header and the footer - which are arbitrarily complex react components.

Creating empty divs

We start by assuming that we have already generated the HTML, JS and CSS files using webflow. The HTML file contains the head and body tags as usual.

We want to insert our React header component at the top of the body, so we add an empty <div> element with a unique id:

<head>...</head><body>
    <div id="webflow-header"></div>
    ... HTML generated by webflow
</body>

As we will see later, the header component will be rendered inside the div above. We will get the ref of the div using the id “webflow-header”

We then want to make place for the footer, which should go right before the closing body tag:

<head>...</head><body>
    <div id="webflow-header"></div>
    ... HTML generated by webflow
    <div id="webflow-footer"></div>
</body>

We also want to create a div where the whole react app will load in. Think of this as an entrypoint for the react app. From here, it will render the header and footer component into the two divs created above. We will do this using the createPortal function provided by React (as we will see later):

<head>...</head><body>
    <div id="webflow-header"></div>
    ... HTML generated by webflow
    <div id="webflow-footer"></div>
    <div id="react-root"></div>
</body>

Adding the React bundle

Just like in a normal react app, we need to add the <script> tag that will load the bundle and run the React app:

<script src = "bundle.js"></script >

Loading the React app

We want to load the react app in the div with the ID “react-root”. This will load the root component of your react app, which can then load the header and footer react component in their respective div tags. The react app can also be used for any other operation like analytics:

ReactDOM.render((    
    <Router />
), document.getElementById("react-root"));

In order to inject the header and footer components into their divs, we need to first get a reference to them. We do so using the document.getElementById function in the root component of the react app

this.headerDiv = document.getElementById("webflow-header");
this.footerDiv = document.getElementById("webflow-footer");

In pages where the divs have not been inserted, the value for this.headerDiv and this.footerDiv will be null. So we need to remember to do a null check before using them.

The render function

In order to inject the components, we have to call the createPortal function from inside the render function. This function takes two arguments:

  • The react component to render
  • The DOM node reference (in our example, it’s this.headerDiv or this.footerDiv)
render() {    
   let result = [];
   if (this.headerDiv) {        
       result.push(ReactDOM.createPortal(<Header />, this.headerDiv));    
   }

   if (this.footerDiv) {        
       result.push(ReactDOM.createPortal(<Footer />, this.footerDiv))    
    }    
   return result;
}
  • Notice that we check that footerDiv and headerDiv are not falsy value - which will be the case when the div elements are not added into the webflow html page.
  • We create an array of JSX elements to inject more than one react component. If the number of components to inject is just one, then we can simply do return ReactDOM.createPortal(<Header />, this.headerDiv)

We have successfully added react components to a webflow generated HTML page.

However…

Since the injection of the components happen after the react bundle is downloaded and run, the user first sees the HTML that’s generated using Webflow, and then sees a jitter as the react components are injected (which occupy their own height and width). Unfortunately, this jitter is quite noticeable.

We can fix this by setting the body tag’s CSS to have display: none initially, and then after the components have been injected, we can set the display to block (in the componentDidMount or useEffect function). This way, the experience for the user is the same as if the whole page is made using React.

So in the componentDidMount / useEffect function, we should do the following

let body = document.getElementsByTagName("body")[0];
if (body !== null) {    
    body.style.display = "block";
}

The above would prevent the jitter and provide a seamless experience for the user.

In Conclusion

We saw how we can inject components into an existing HTML page generated via Webflow using the ReactDOM.createPortal function.

This method allows for quicker development of relatively static web pages saving you money. As a reference, we at SuperTokens use this method. Our home page is made completely using Webflow, excepting for the header and footer - which are injected using the method shown above.

Cofounder and CTO of SuperTokens. Building open source user authentication that is quick and customizable. BEng from Imperial College of London