How to integrate a react component into an Expressjs app

In a previous post, I walked thru converting an expressjs partial into a react component. Now that I have that set up, in this post I’ll define the subsequent step of integrating the component into the app.

Our component is built as an exportable ES6 module, but it is not yet imported anywhere. This project uses a main.js on the frontend that I will import the module into.

To do do, I’ll need to add the following line at the top of main.js:

import ReactNav from "./dist/bca-react-component-library/nav/nav.js";

This will import the default export from nav.jsx for use in main.js. The default component exported from the nav file accepts two props, customClass and items. Both props are by default set as empty arrays.

export default function ReactNav({ customClass = [], items =[] }) {
    //component code
}

This means I’ll need to pass array arguments for each of these props when I call the nav in main.js. To do this, I’ll set up a loadNav() function. Inside of loadNav I’ll define the two arrays:

  const navItems = [
    { name: "Start Page", link: "/" },
    { name: "Bedtime Checklist", link: "/bedtime-checklist" },
    { name: "Add Checklist", link: "/admin/add-checklist" },
    { name: "All Checklists", link: "/admin/all-checklists" },
  ];
const navClasses = ["navbar", "navbar-expand-lg", "navbar-light", "bg-light"];

The first array above builds out an array of objects, each with a name and link property. The second is an array of class names as strings.

Now that the two arrays are prepared, I can query the DOM for the element I want to insert my nav into and then create and render that item:

const navRoot = createRoot(document.getElementById("react-nav"));
  navRoot.render(React.createElement(ReactNav, { customClass: navClasses, items: navItems }));

Since this project works with Express views and Handlebars templating, the integration here is slightly different than a fully react-based app. Instead of a single react-app entry point in the DOM, I have broken that out into multiple entry points, based on the page location of specific components.

So that sets up our loadNav function. The full function looks like this:

function loadNav() {
  const navItems = [
    { name: "Start Page", link: "/" },
    { name: "Bedtime Checklist", link: "/bedtime-checklist" },
    { name: "Add Checklist", link: "/admin/add-checklist" },
    { name: "All Checklists", link: "/admin/all-checklists" },
  ];

  const navClasses = ["navbar", "navbar-expand-lg", "navbar-light", "bg-light"];

  const navRoot = createRoot(document.getElementById("react-nav"));
  navRoot.render(React.createElement(ReactNav, { customClass: navClasses, items: navItems }));
}

function loadChecklistItemAdd() {
  if (!document.getElementById("bca-checklist-item-add")) {
    return;
  }
  const checklistItemAddRoot = createRoot(document.getElementById("bca-checklist-item-add"));

  checklistItemAddRoot.render(
    React.createElement(BCAChecklistItemAdd)
  );
}

In my Express view template there is a call to a header partial:

{{> header }}

I’m going to keep that call, and I’ll modify the contents of the partial itself to set up the target container form my nav component. Inside of header.hbs:

<header>
    <div id="react-nav"></div>
</header>

Now we need to actually call our function. For that, I have set up a runAllFunctions function that is triggered by the DOM load event:

window.addEventListener("load", runAllFunctions);

function runAllFunctions() {
  //call any other functions that should fire on load
  loadNav();
}

Now, when our app loads the script, it will fire our loadNav function, look for the target html element and once found, inject our nav into the DOM.

That’s all for now!


Posted

in

by

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *