An open API service indexing awesome lists of open source software.

https://github.com/raheesahmed/nextjs-state

🚀 Type-safe state management solution for Next.js applications with built-in persistence and server component support.
https://github.com/raheesahmed/nextjs-state

nextjs nextjs-state persistence react react-hooks server-components state state-management state-management-in-react typescript web-development web-development-tools

Last synced: about 2 months ago
JSON representation

🚀 Type-safe state management solution for Next.js applications with built-in persistence and server component support.

Awesome Lists containing this project

README

          

# Next State

A modern, type-safe state management solution designed specifically for Next.js applications. Next State provides a minimal yet powerful API with built-in support for server components, persistence, and development tools.

[![npm version](https://badge.fury.io/js/nextjs-state.svg)](https://badge.fury.io/js/nextjs-state)
[![Bundle Size](https://img.shields.io/bundlephobia/minzip/nextjs-state)](https://bundlephobia.com/package/nextjs-state)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Features

- 🎯 **Type-safe**: Full TypeScript support with type inference and strict null checks
- ⚡ **Lightweight**: Less than 1KB minified and gzipped for optimal bundle size
- 🔄 **Middleware**: Extensible middleware system for logging, persistence, validation, and more
- 💾 **Persistence**: Built-in storage adapters for localStorage and indexedDB with migration support
- 🎨 **Selectors**: Efficient state access with automatic memoization to prevent unnecessary re-renders
- 🖥️ **DevTools**: Integrated development tools for debugging and time-travel
- 🚀 **Server Components**: First-class support for Next.js App Router and Server Components
- 🔄 **Optimistic Updates**: Built-in support for optimistic UI updates with server synchronization
- 📦 **Zero dependencies**: Only React as a peer dependency for minimal footprint

## Installation

```bash
npm install nextjs-state
# or
yarn add nextjs-state
# or
pnpm add nextjs-state
```

## Quick Start

```tsx
import { createNextState } from 'nextjs-state';

// 1. Define your state type
interface CounterState {
count: number;
lastUpdated: string;
}

// 2. Create your state
const { useNextState } = createNextState({
initialState: {
count: 0,
lastUpdated: new Date().toISOString(),
},
// Optional configuration
options: {
// Enable DevTools in development
devTools: process.env.NODE_ENV === 'development',
// Persist state to localStorage
storage: {
key: 'counter-app',
version: '1.0',
},
},
});

// 3. Use in your components
function Counter() {
// Access the full state
const { state, setState } = useNextState();

// Or use a selector for better performance
// const count = useNextState(state => state.count);

const increment = () => {
setState({
count: state.count + 1,
lastUpdated: new Date().toISOString(),
});
};

return (


Count: {state.count}


Last Updated: {new Date(state.lastUpdated).toLocaleString()}


Increment

);
}
```

## Complete Example

Here's a comprehensive example showcasing all features including state management, middleware, theming, and UI components:

```tsx
'use client';

import {
createNextState,
createLoggingMiddleware,
createPersistenceMiddleware,
} from 'nextjs-state';

// Define complete app state
interface AppState {
counter: {
value: number;
history: number[];
lastUpdated: string;
};
todos: {
items: Array<{
id: number;
text: string;
completed: boolean;
priority: 'low' | 'medium' | 'high';
}>;
filter: 'all' | 'active' | 'completed';
};
theme: {
mode: 'light' | 'dark';
fontSize: 'small' | 'medium' | 'large';
accentColor: string;
};
user: {
preferences: {
notifications: boolean;
autoSave: boolean;
};
lastActivity: string;
};
}

// Create middleware stack
const loggingMiddleware = createLoggingMiddleware();
const persistenceMiddleware = createPersistenceMiddleware('app-state');

// Custom analytics middleware
const analyticsMiddleware = (state: AppState, nextState: AppState) => {
if (state.counter.value !== nextState.counter.value) {
console.log('Analytics: Counter changed', {
from: state.counter.value,
to: nextState.counter.value,
});
}
return nextState;
};

// Custom validation middleware
const validationMiddleware = (state: AppState, nextState: AppState) => {
if (nextState.counter.value < 0) {
console.warn('Validation: Negative counter values not allowed');
return state;
}
return nextState;
};

// Initialize state
const { useNextState } = createNextState({
initialState: {
counter: {
value: 0,
history: [],
lastUpdated: new Date().toISOString(),
},
todos: {
items: [],
filter: 'all',
},
theme: {
mode: 'light',
fontSize: 'medium',
accentColor: '#3b82f6',
},
user: {
preferences: {
notifications: true,
autoSave: true,
},
lastActivity: new Date().toISOString(),
},
},
middleware: [loggingMiddleware, validationMiddleware, analyticsMiddleware, persistenceMiddleware],
});

// Action creators
const actions = {
counter: {
increment: (state: AppState) => ({
...state,
counter: {
value: state.counter.value + 1,
history: [...state.counter.history, state.counter.value],
lastUpdated: new Date().toISOString(),
},
}),
},
theme: {
toggleMode: (state: AppState) => ({
...state,
theme: {
...state.theme,
mode: state.theme.mode === 'light' ? 'dark' : 'light',
},
}),
},
// ... more actions
};

// Example component
function Counter() {
const { state, setState } = useNextState();

return (


Counter: {state.counter.value}


setState(actions.counter.increment)}>Increment
History: {state.counter.history.join(', ')}


);
}
```

For a complete working example with all features and beautiful UI components, check out our [demo repository](https://github.com/yourusername/nextjs-state-demo).

## Advanced Usage

### Using with Next.js App Router

```tsx
// app/providers.tsx
'use client';

import { createNextState } from 'nextjs-state';

interface AppState {
theme: 'light' | 'dark';
user: {
name: string;
preferences: Record;
} | null;
}

export const { useNextState } = createNextState({
initialState: {
theme: 'light',
user: null,
},
});

// app/layout.tsx
import { Providers } from './providers';

export default function RootLayout({ children }) {
return (


{children}


);
}
```

### Using Selectors for Performance

```tsx
import { createNextState, useSelector } from 'nextjs-state';

interface DeepState {
users: {
list: Array<{
id: number;
name: string;
settings: {
theme: string;
notifications: boolean;
};
}>;
selectedId: number | null;
};
}

const { useNextState } = createNextState({
initialState: {
users: {
list: [],
selectedId: null,
},
},
});

function SelectedUserSettings() {
const state = useNextState();
const selectedUser = useSelector(state, (s) =>
s.users.list.find((u) => u.id === s.users.selectedId)
);

if (!selectedUser) return

No user selected
;

return (


{selectedUser.name}'s Settings


Theme: {selectedUser.settings.theme}


Notifications: {selectedUser.settings.notifications ? 'On' : 'Off'}



);
}
```

## Best Practices

1. **State Organization**

- Keep state minimal and focused
- Split large state into smaller, focused states
- Use TypeScript interfaces for better type safety

2. **Performance**

- Use selectors for expensive computations
- Avoid storing derived state
- Split large components into smaller ones

3. **Middleware Usage**
- Order middleware from most to least important
- Use middleware for cross-cutting concerns
- Keep middleware pure and side-effect free

## API Reference

### `createNextState`

Creates a new state instance.

```tsx
function createNextState(config: {
initialState: T;
middleware?: Array<(state: T, nextState: T) => T>;
}): {
useNextState: () => {
state: T;
setState: (newState: T | ((prevState: T) => T)) => void;
};
};
```

### `useSelector`

Creates a memoized selector.

```tsx
function useSelector(hook: NextStateHook, selector: (state: T) => S): S;
```

### Middleware Creators

#### `createLoggingMiddleware`

```tsx
function createLoggingMiddleware(): (state: T, nextState: T) => T;
```

#### `createPersistenceMiddleware`

```tsx
function createPersistenceMiddleware(key: string): (state: T, nextState: T) => T;
```

## Documentation

For more detailed documentation, please visit our documentation site:

- [Getting Started](./docs/getting-started/core-concepts.md) - Learn the core concepts and philosophy
- [API Reference](./docs/api/api-reference.md) - Complete API documentation
- [Guides](./docs/guides/) - In-depth guides for specific use cases
- [Middleware Guide](./docs/guides/middleware.md) - Learn how to create and use middleware
- [Testing Guide](./docs/guides/testing.md) - Best practices for testing
- [Technical Documentation](./docs/technical_documentation.md) - Detailed technical information

## Contributing

We welcome contributions! Please see our [Contributing Guide](./CONTRIBUTING.md) for more details.

## License

MIT