Managing state efficiently in a Next.js App Router environment can be challenging, especially when dealing with Server Components and Client Components. This is where next-state-adapter comes into playโproviding a seamless solution for managing state across your Next.js application.
๐ Why next-state-adapter?
next-state-adapter is a state management adapter specifically designed for Next.js App Router. It offers:
-
Seamless integration with Next.js (
app/
directory) - Efficient server-side data handling for initial state hydration
- Simplified state hydration in Client Components
- Support for class components with an easy-to-use Higher-Order Component (HOC)
- Works with various state management libraries like Mobx, Zustand, Jotai, Recoil, and others, giving you the flexibility to use your preferred state manager.
๐ฆ Getting Started
First, install the package using npm or yarn:
npm install next-state-adapter
# or
yarn add next-state-adapter
๐ Setting Up next-state-adapter
1. Create the Root Store and Provider
Start by setting up the root store and necessary hooks for state management:
// ~/store/config.ts
'use client';
import {RootStore} from "@/store/root";
import {createProvider, useStore} from "next-state-adapter";
const makeStore = () => new RootStore();
export const useAppStore = useStore.withTypes<RootStore>();
export const useAppStoreHydration = useStoreHydration.withTypes<RootStore>();
export const StoreProvider = createProvider(makeStore);
// ~/store/withStore.ts
import {withStore as withStoreHoc} from "next-state-adapter";
export const withStore = withStoreHoc.withTypes<RootStore>();
2. Wrap Your Application with the Store Provider
Now, wrap your application in the StoreProvider
component inside layout.tsx
:
// ~/app/layout.tsx
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<StoreProvider>
{children}
</StoreProvider>
</body>
</html>
);
}
3. Use the Store in a Client Component
Letโs create a Todo List component that fetches initial data from the server and hydrates the client-side store:
// ~/todos/list.tsx
'use client';
const TodoList = ({ initialTodos }: { initialTodos: Todo[] }) => {
const { todos } = useAppStoreHydration((store) => {
store.todos.init(initialTodos);
});
return (
<ul>
{todos.todos.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
);
};
4. Use the Component in a Server Component
Now, fetch the initial state on the server and pass it to TodoList
:
// ~/app/todos/page.tsx
export default async function Todos() {
const initialTodos = await fetchTodos(); // Fetching initial data on server side
return <TodoList initialTodos={initialTodos} />;
}
5. Support for Class Components
If you're using class components, next-state-adapter
provides an easy way to inject the store via HOC:
type Props = {
store: RootStore;
initialUsers: User[];
};
class Users extends Component<Props> {
render() {
const { store } = this.props;
const users = store.users.users;
return (
<div>
{users.map((user) => (
<div key={user.id}>{user.id}</div>
))}
</div>
);
}
}
// Inject store and hydrate with initialUsers
typescript
export const UsersList = withStore(Users, (store, props) => {
store.users.init(props.initialUsers);
});
// Use in a server component
export default async function UsersPage() {
const initialUsers = await fetchUsers();
return <UsersList initialUsers={initialUsers} />;
}
๐ฏ Final Thoughts
The next-state-adapter simplifies state management in Next.js App Router applications by providing a structured, optimized. Whether you are working with functional components, class components, or server-side data hydration, this adapter ensures a smooth developer experience.
It also supports a wide range of state management libraries like Mobx, Zustand, Jotai, Recoil, and others, so you can integrate it with your preferred solution effortlessly.
Give it a try in your Next.js App Router project and experience a more efficient way to manage state!
๐ Check out the official documentation: next-state-adapter docs
๐ Link to npm: next-state-adapter npm
Top comments (2)
cool :)
Informative and straight to the point