Changing JavaScript frameworks and coding them in React

Joe Alongi
9 min readDec 25, 2024

--

In responsive navigation menus in Angular, it is apparent that there are many principles and theories behind navigation across the virtual Document Object Model (DOM). As a system progresses the technology supporting it often undergoes change, from patches to updates and frameworks to cloud migrations, knowing how to move across frameworks is a valuable skill.

As a cursory example of JavaScript’s fluidity, it is important to understand that many of the frameworks developers work in and on throughout the day are extensible variations.

In a synergistic way, many of the fundamental programming concepts like inheritance, parameterization, and bundling, lend themselves to compounded tooling for developers. When working through a major refactoring effort like moving from Angular to React, it is important to remember that these frameworks sit on top of vanilla JavaScript.

Structuring the menu in React

Starting with the existing `navbar.component.html` evaluate from top to bottom, what needs to change from the Angular to React framework to allow the application to load without error. One notable consideration is the change of the file format, when moving from Angular to React, is condensing the component into one file, instead of four. A lot of the HTML markup is valuable in both React and Angular, the noticeable traits to be changed are the JavaScript elements.

A first step begins with creating a function, the layout function for a React component, which will return the contents of the Angular file as HTML in the form of JSX syntax. When moving the contents of the navbar.component.html file into the return method, there will be a series of highlighted errors from linters and formatters. Eslint and Prettier alone can help identify these errors, though working through this, the main differences will unfold below.

export default function Navbar() {
return (
<>
<header id="header">
<div id="navbar" class="flex-row">
<a
class="logo flex-row-item"
href="/"
target="_self"
rel="noreferrer noopener"
aria-label="Buffalo Compute Link"
type="link"
><img
src="/assets/BuffaloComputeAppAlt.png"
loading="eager"
height="30"
width="30"
alt="Buffalo Compute Logo"
/></a>
<button
class="mobile-menu-icon flex-row-item"
aria-label="Buffalo Compute Mobile Menu"
type="button"
(click)="toggleMobileMenu()"
clickable
>
<img
src="/assets/mobile-menu-icon.svg"
loading="eager"
height="30"
width="30"
alt="Buffalo Compute Mobile Menu Icon"
/>
</button>

<nav class="menu flex-row-item">
<ul class="flex-row">
@for (link of links; track $index) {
<li class="flex-row-item">
<a
[href]="link.href"
target="_self"
rel="noreferrer noopener"
type="link"
>{{ link.text }}</a
>
</li>
}
</ul>
</nav>
</div>
</header>
@if (navbarMobileVisible === true) {
<nav id="navbar-mobile" aria-label="Buffalo Compute Navbar Mobile">
<ul class="flex-column">
@for (link of links; track $index) {
<li class="flex-row-item">
<a
[href]="link.href"
target="_self"
rel="noreferrer noopener"
type="link"
>{{ link.text }}</a
>
</li>
}
</ul>
</nav>
}

<div id="announcement" class="flex-row">
<span class="flex-row-item">This is an announcement!</span>
</div>
</>
)
}

A quick and easy start is renaming all of the classes to className from the html reference to the React JSX reference so that the CSS properly inherits the styled values. Find and replace within Visual Studio Code can help quickly adapt this, finding class, and replacing it with className.

export default function Navbar() {
return (
<>
<header id="header">
<div id="navbar" className="flex-row">
<a
className="logo flex-row-item"
href="/"
target="_self"
rel="noreferrer noopener"
aria-label="Buffalo Compute Link"
type="link"
><img
src="/assets/BuffaloComputeAppAlt.png"
loading="eager"
height="30"
width="30"
alt="Buffalo Compute Logo"
/></a>
<button
className="mobile-menu-icon flex-row-item"
aria-label="Buffalo Compute Mobile Menu"
type="button"
(click)="toggleMobileMenu()"
clickable
>
<img
src="/assets/mobile-menu-icon.svg"
loading="eager"
height="30"
width="30"
alt="Buffalo Compute Mobile Menu Icon"
/>
</button>

<nav className="menu flex-row-item">
<ul className="flex-row">
@for (link of links; track $index) {
<li className="flex-row-item">
<a
[href]="link.href"
target="_self"
rel="noreferrer noopener"
type="link"
>{{ link.text }}</a
>
</li>
}
</ul>
</nav>
</div>
</header>
@if (navbarMobileVisible === true) {
<nav id="navbar-mobile" aria-label="Buffalo Compute Navbar Mobile">
<ul className="flex-column">
@for (link of links; track $index) {
<li className="flex-row-item">
<a
[href]="link.href"
target="_self"
rel="noreferrer noopener"
type="link"
>{{ link.text }}</a
>
</li>
}
</ul>
</nav>
}

<div id="announcement" className="flex-row">
<span className="flex-row-item">This is an announcement!</span>
</div>
</>
)
}

Another quick step is removing the /assets/ folder from the img tags and their src attribute to point to the public folder within the React application. As the Node.js server starts and hosts the React application, the public folder is hosted at the domain path, simplifying image hosting. These images can be stored in a folder within the application to make them private, the public folder simply provides an efficient way to access media.

export default function Navbar() {
return (
<>
<header id="header">
<div id="navbar" class="flex-row">
<a
class="logo flex-row-item"
href="/"
target="_self"
rel="noreferrer noopener"
aria-label="Buffalo Compute Link"
type="link"
><img
src="/BuffaloComputeAppAlt.png"
loading="eager"
height="30"
width="30"
alt="Buffalo Compute Logo"
/></a>
<button
class="mobile-menu-icon flex-row-item"
aria-label="Buffalo Compute Mobile Menu"
type="button"
(click)="toggleMobileMenu()"
clickable
>
<img
src="/mobile-menu-icon.svg"
loading="eager"
height="30"
width="30"
alt="Buffalo Compute Mobile Menu Icon"
/>
</button>

<nav class="menu flex-row-item">
<ul class="flex-row">
@for (link of links; track $index) {
<li class="flex-row-item">
<a
[href]="link.href"
target="_self"
rel="noreferrer noopener"
type="link"
>{{ link.text }}</a
>
</li>
}
</ul>
</nav>
</div>
</header>
@if (navbarMobileVisible === true) {
<nav id="navbar-mobile" aria-label="Buffalo Compute Navbar Mobile">
<ul class="flex-column">
@for (link of links; track $index) {
<li class="flex-row-item">
<a
[href]="link.href"
target="_self"
rel="noreferrer noopener"
type="link"
>{{ link.text }}</a
>
</li>
}
</ul>
</nav>
}

<div id="announcement" class="flex-row">
<span class="flex-row-item">This is an announcement!</span>
</div>
</>
)
}

After moving the images from the assets folder to the public folder these images should be able to be referenced directly from the src property. In the application these files, are read as HTML within JSX and can make use of the HTML properties like loading, alt, and styling.

Enabling the responsive menu in React

In the Buffalo Compute Mobile Menu button markup, the click event listener will be converted to a custom JavaScript function in React, and the clickable property will be removed. In React a state management library, with hooks to access these as functions can be called in place of the property based functions established within navbar.component.ts in Angular.

Through the useState hook, an on/off state can be activated by using the onClick listener again to switch the boolean default value of false to true and true to false. To show and hide the mobile navigation bar, in place of the @ if block, creating a ternary based class will accomplish the same outcome. When the React state is adjusted by a button click, the expression as a dynamic className will evaluate the state and refresh the virtual DOM to reflect the changes in the superclasses and subclasses designated within the bundled code.

import React, { useState } from "react";

export default function Navbar() {
const [isOpen, setIsOpen] = useState(false);

const toggle = () => setIsOpen(!isOpen);

return (
<>
<header id="header">
<div id="navbar" class="flex-row">
<a
class="logo flex-row-item"
href="/"
target="_self"
rel="noreferrer noopener"
aria-label="Buffalo Compute Link"
type="link"
><img
src="/BuffaloComputeAppAlt.png"
loading="eager"
height="30"
width="30"
alt="Buffalo Compute Logo"
/></a>
<button
class="mobile-menu-icon flex-row-item"
aria-label="Buffalo Compute Mobile Menu"
type="button"
onClick={toggle}
>
<img
src="/mobile-menu-icon.svg"
loading="eager"
height="30"
width="30"
alt="Buffalo Compute Mobile Menu Icon"
/>
</button>

<nav class="menu flex-row-item">
<ul class="flex-row">
@for (link of links; track $index) {
<li class="flex-row-item">
<a
[href]="link.href"
target="_self"
rel="noreferrer noopener"
type="link"
>{{ link.text }}</a
>
</li>
}
</ul>
</nav>
</div>
</header>
<nav id="navbar-mobile" aria-label="Buffalo Compute Navbar Mobile" className = {isOpen ? '' : 'hidden'}>
<ul class="flex-column">
@for (link of links; track $index) {
<li class="flex-row-item">
<a
[href]="link.href"
target="_self"
rel="noreferrer noopener"
type="link"
>{{ link.text }}</a
>
</li>
}
</ul>
</nav>

<div id="announcement" class="flex-row">
<span class="flex-row-item">This is an announcement!</span>
</div>
</>
)
}

State management can occur at a component above this in order if required and passed down as a function, often as an initial step it is good to establish components within themselves and then restructure. The more functionality a component like this contains, the more complexity it contains, and becomes more difficult to address, splitting code eventually becomes an obvious choice.

Rendering the dynamic menu in React

As a next step, converting the @ for block to a JavaScript map function allows for the looping of the links array previously established within the navbar.component.ts that is now introduced into the new React function. In this function, TypeScript annotates the values within the object that is mapping over the static elements to introduce the dynamic values, this can be stored as a JSON file or retrieved as an API response as well. The values from the links array are iterated over similarly to a for loop, although in this sense, this maps the data through dot notation onto the static elements that emit these values as they render.

import React, { useState } from "react";

const links = [
{ number: 0, text: "Home", href: "/" },
{ number: 1, text: "About", href: "/about" },
{ number: 2, text: "Articles", href: "/articles" },
{ number: 3, text: "Blueprints", href: "/blueprints" },
{ number: 4, text: "Tools", href: "/tools" },
];

type LinkT = {
number: number;
text: string;
href: string;
};

export default function Navbar() {
const [isOpen, setIsOpen] = useState(false);

const toggle = () => setIsOpen(!isOpen);

return (
<>
<header id="header">
<div id="navbar" className="flex-row">
<a
className="logo flex-row-item"
href="/"
target="_self"
rel="noreferrer noopener"
aria-label="Buffalo Compute Link"
type="link"
>
<img
src="/BuffaloComputeAppAlt.png"
loading="eager"
height="30"
width="30"
alt="Buffalo Compute Logo"
/>
</a>
<button
className="mobile-menu-icon flex-row-item"
aria-label="Buffalo Compute Mobile Menu"
type="button"
onClick={toggle}
>
<img
src="/mobile-menu-icon.svg"
loading="eager"
height="30"
width="30"
alt="Buffalo Compute Mobile Menu Icon"
/>
</button>

<nav className="menu flex-row-item">
<ul className="flex-row">
{links?.map((data: LinkT) => (
<li className="flex-row-item" key={data?.number}>
<a
href={data?.href}
target="_self"
rel="noreferrer noopener"
type="link"
>
{data?.text}
</a>
</li>
))}
</ul>
</nav>
</div>
</header>
<nav
id="navbar-mobile"
aria-label="Buffalo Compute Navbar Mobile"
className={isOpen ? "" : "hidden"}
>
<ul className="flex-column">
{links?.map((data: LinkT) => (
<li className="flex-row-item" key={data?.number}>
<a
href={data?.href}
target="_self"
rel="noreferrer noopener"
type="link"
>
{data?.text}
</a>
</li>
))}
</ul>
</nav>

<div id="announcement" className="flex-row">
<span className="flex-row-item">This is an announcement!</span>
</div>
</>
);
}

The bracket reference here is related to the JSX markup’s ability to indirectly pass inheritance from parent to child as the function within the brackets computes. Implementing the contents of these mapped elements can be instructed from components above this, with objects passed as props or properties, this construct becomes valuable for API based content.

Invoking the menu component in React

Similarly to the app.component.html in Angular, importing the <Navbar /> component is required to render the component within the application. In this final step, invoking the recently created component will allow for rendering it within the application. Through this Angular to React transformation, the component now leverages JavaScript functions and methods directly in place of derived references within the Angular framework.

import React from "react";
import "./App.css";
import Navbar from "./components/menu/Navbar";

function App() {
return (
<div className="App">
<Navbar />
</div>
);
}

export default App;

In many scenarios, developing applications plainly allows for a quicker speed to delivering a release of new software applications. As JavaScript gains more and more traction, so do the many frameworks, packages, and solutions. In development of these reference based application architectures, the caveat seems to become the abstraction that they employ to ‘simplify’ the hands-on development that is often enabled by hard skills.

Join in on the adventure at heyitsjoealongi.com and on X, Instagram, GitHub, and LinkedIn. For more articles like this subscribe on Substack.

--

--

No responses yet