React and Next.js

Plan: Composable Developer

Lesson 8 of 22 · 15 min

Introduction

The backbone of the Makeswift frontend is React, the JavaScript library for building user interfaces. The custom components you build for the editor are React components, and React’s model of composing UI from modular, reusable pieces is what makes Makeswift’s visual editing possible. A solid grasp of React is the foundation for successfully customizing your Makeswift application.

React

React is a JavaScript-powered library for rapidly and easily building user interfaces.

Compared with a templating language like Handlebars in Stencil, React components offer similar capabilities for expressing dynamic data but also encompass much more. React interfaces are a tree of modular components, which are actually JavaScript functions encapsulating both the logic and presentational markup relevant to a specific piece of UI.

React is a large topic. If you’re new to the technology, see the official guide to start. The following are some of the basic concepts.

Functions and JSX

React components are functions that return JSX code - an HTML-like markup that allows mixing in JavaScript expressions.

JavaScript Expressions

Wherever braces appear within JSX, the code within them is a JavaScript expression. This is essential for working with dynamic data.

Referencing dynamic values, conditional output, loops, and similar constructs require no specialized syntax. Familiar JavaScript syntax like object notation, comparison operators, and array functions are used for these tasks.

State

State values provide the “memory” of a React component, tracking data that changes in response to user interaction or external systems.

State is key to creating highly dynamic UI, making it easy to incorporate even very complex combinations of states by simply describing conditional output with JSX.

An Example

The following example demonstrates a straightforward implementation of the concepts we’ve described.

function BlogPost({
article,
showTags
}) {
{/* State to track a user's interaction */}
const [liked, setLiked] = useState(false);
const activateLike = () => {
// ... send request
setLiked(true);
}
return (
<article>
{/* Outputting a simple object value */}
<h1>{article.title}</h1>
<div>
{article.body}
</div>
{/* Using comparison for an "IF" */}
{showTags && (article.tags.length > 0) && (
<ul>
{/* A simple array function to loop over a value */}
{article.tags.map(tag => (
<li>{tag}</li>
))}
</ul>
)}
<div>
{/* Ternary operators work as well
This time examining state for what to output. */}
{liked ? (
<span>You liked this</span>
) : (
<button onClick={activateLike}>Like</button>
)}
</div>
</article>
);
}

Next.js

In a fully composable application like Catalyst, Next.js is the central full-stack framework that ties everything together. Built on React, it adds routing, data fetching, and server-side rendering, and it’s responsible for orchestrating the communication with Makeswift and rendering your components — both on the public-facing storefront and within the editor itself. In practice, Makeswift provides Next.js with a snapshot of the component tree built in the editor for a page (or an individual component), while Next.js informs Makeswift of the details of your custom components and renders pages within the editor.

Client vs. Server Components

Given their JavaScript foundation and frequent emphasis on interactivity, React components have traditionally been processed and rendered within the client (the web browser, for example, in a web application).

The Next.js App Router architecture makes it possible to utilize the newer React Server Component pattern. Server components bring their own advantages, allowing server-side logic like data fetching to be tightly coupled with the rendered component. Client and server components each have their purpose, and applications are typically built with a combination of both.

Currently, the custom components you create for the Makeswift builder must be client components. Server components can, however, still be used elsewhere in your application (provided you are using the App Router).

Resources