December 12, 2023
State Management in Next.js with URL-Based Data Persistence
INTRODUCTION
State management is a pivotal part of app development, often leading to complexities and challenges. While tools like Next.js with React offer hooks like useReducer
and useContext
for state management, they sometimes lead to unnecessary re-renders and pose difficulties in preserving application state.
In this blog, we introduce an alternative approach to handle state persistence without the intricacies of additional packages or complex hooks. Our method utilizes the URL to manage state data, providing a simple yet efficient solution for state persistence across page refreshes.
Implementation in a Next.js Application
Let's start by setting up our Next.js application:
1. Installation
npx create-next-app@latest
Ensure installation with TypeScript and Next.js 13 app router, customizing import statements as @
.
2. Implementing URL-Based State Management app/form/page.tsx
'use client'
import React, { useState, ChangeEvent, FormEvent } from 'react';
import { useRouter, useSearchParams } from "next/navigation";
interface FormData {
name: string;
email: string;
}
const Form = () => {
const router = useRouter();
const searchParams = useSearchParams();
const [formData, setFormData] = useState<FormData>({
name: '',
email: '',
});
const handleInputChange = (e: ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setFormData({
...formData,
[name]: value,
});
};
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
// Retrieve current search params
const current = new URLSearchParams(Array.from(searchParams.entries()));
// Set name to url param and encode it
current.set('name', encodeURIComponent(formData.name));
// Set email to url param and encode it
current.set('email', encodeURIComponent(formData.email));
// set objects to string
const search = current.toString();
const query = search ? `?${search}` : '';
// Go back to the home page with the new params.
router.push(`/${query}`, { scroll: false });
};
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="name">Name:</label>
<input
type="text"
id="name"
name="name"
value={formData.name}
onChange={handleInputChange}
required
/>
</div>
<div>
<label htmlFor="email">Email:</label>
<input
type="email"
id="email"
name="email"
value={formData.email}
onChange={handleInputChange}
required
/>
</div>
<button type="submit">Submit</button>
</form>
);
};
export default Form;
The form component captures user data and appends it to the URL as query parameters upon form submission. The url should look like this; http://localhost:3000/?John%20Doe=john%40example.com
The homepage component retrieves and displays the data from the URL parameters.
"use client";
import React from "react";
import { useSearchParams } from "next/navigation";
export default function Home() {
const searchParams = useSearchParams();
// Now, we get the param from the URL and decode them.
const name = decodeURIComponent(searchParams.get("name") as string);
const email = decodeURIComponent(searchParams.get("process") as string);
return (
<main className="flex justify-start md:justify-center items-center w-full md:min-h-screen gap-2 flex-col md:py-5">
<p>{name}</p>
<p>{email}</p>
</main>
);
}
Now, upon submitting the form, the URL should reflect the user input, enabling seamless data persistence.
CONCLUSION
By harnessing the URL to manage and persist state data in a Next.js application, we've established a straightforward yet effective method. This approach mitigates the need for complex state management libraries or additional hooks, offering a clean solution that ensures data persistence across page navigations or refreshes.
Implementing state management with URL-based data persistence provides a valuable alternative, promoting a more user-friendly experience without compromising on simplicity.
418 views