Innovative Tech Development
Implementing Dynamic Routing in a Commerce Application with Sanity's Router and React
Building
a
seamless,
efficient
routing
system
for
a
commerce
application
can
significantly
enhance
user
experience
and
application
performance.
This
article
dives
deep
into
the
journey
of
integrating
Sanity's
router
with
React
to
develop
a
dynamic,
scalable
routing
framework
tailored
for
a
commerce
tool.
Integrating Sanity's router into our commerce application wasn't just about coding—it involved significant research and exploration. Much of the development time was spent delving into API documentation and searching for practical examples to understand how best to utilise Sanity's routing capabilities within our React application.
The primary research began with exploring the Sanity GitHub repository, which hosts the latest code for the router package. The directory of interest was sanity/src/router, where the core routing logic and utilities are maintained. This exploration was crucial for understanding the underlying mechanics of Sanity's routing system and how it could be leveraged to meet our application's specific needs.
A breakthrough came from a demo within the README file at sanity/src/router/README.md on GitHub. This demo provided a glimpse into the practical implementation of the router, showcasing how routes could be dynamically created and managed within a Sanity plugin. It served as a vital reference point, translating the theoretical aspects of the API documentation into a tangible example that could be adapted for our purposes.
Additional documentation from Sanity's official site played a pivotal role throughout this journey. The pages on Router and route provided detailed insights into the API's capabilities, options, and configurations. These resources were instrumental in understanding the nuances of route creation, navigation handling, and the integration of dynamic routing within our commerce tool.
The process was ultimately rewarding despite the lack of straightforward examples and the challenge of piecing together information from various sources. It pushed the boundaries of what we could achieve with Sanity's router, developing a flexible, dynamic routing system tailored specifically for our commerce application. The experience underscores the importance of thorough research, experimentation, and leveraging available resources to implement practical solutions in software development.
This example leverages TypeScript for solid typing, ensuring our application's navigation logic is clear and error-resistant.
Defining Constants and Types
First, we define the constant settings that will underpin our routing and view logic:
type ViewType = "order" | "product" | "customer";
type ActionType = "create" | "view" | "edit";
type StateType = {
action?: ActionType;
id?: string;
view: ViewType;
};
enum CommerceRoutes {
view = "/view/:view",
create = "/view/:view/:action",
action = "/view/:view/:action/:id",
}
export { CommerceRoutes };
export type { ViewType, ActionType, StateType };
These constants and types (ViewType, ActionType, and StateType) define the possible views (like orders or products), actions (such as create or edit), and the state shape our application can take. CommerceRoutes is an enumeration that maps our route patterns to meaningful names, making our routing table easy to read and maintain.
Building the Commerce Tool
Next, we create a new tool that incorporates these routes:
import { route } from '@sanity/base/router'
const commerceTool = () => {
return {
title: "Commerce",
name: "commerce-tool",
component: () => CommerceTool(),
router: route.create("/", [
...Object.values(CommerceRoutes).map((item) => route.create(item)),
]),
};
};
This tool, named "Commerce", uses Sanity's router to define its routing logic. By iterating over our CommerceRoutes enumeration, we dynamically create routes for our application, keeping our code DRY and routing table flexible.
Creating a Plugin
To encapsulate our tool within a broader application context, we wrap it in a plugin:
import { definePlugin } from 'sanity'
const commercePlugin = () =>
definePlugin({
name: "commerce-plugin",
tools: [commerceTool()],
});
export { commercePlugin };
This "commerce-plugin" plugin can be easily integrated into any Sanity studio, allowing for quick setup and scalability across different workspaces.
Defining the Main View
Finally, we define the main view component that renders UI based on the current route's state:
import { ActionType, ViewType, StateType } from "@/studio/plugins/commerce/constants";
import dynamic from "next/dynamic";
type Props = {
state: StateType;
};
const viewMap: Partial<Record<ViewType, Record<ActionType, any>>> = {
product: {
edit: dynamic(() => import("./product/product-edit-view")),
view: dynamic(() => import("./product/product-view")),
create: dynamic(() => import("./product/product-create-view")),
},
// Additional view mappings can be added here
};
export default function View({ state }: Props) {
const Component = state.action ? viewMap[state.view]?.[state.action] : null;
return Component ? <Component state={state} /> : <div>Not found</div>;
}
This component, View, uses a dynamic import strategy to load the appropriate component based on the current state. This lazy-loading approach ensures that our application only loads the necessary code, improving performance.
Conclusion
We've created a scalable, maintainable, and performance-optimised routing system by integrating Sanity's router with a dynamic component loading strategy in a TypeScript React application. This approach allows for clear separation of concerns, easy debugging, and a solid foundation for expanding our commerce application.