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.
- Host: GitHub
- URL: https://github.com/raheesahmed/nextjs-state
- Owner: RaheesAhmed
- License: mit
- Created: 2024-12-10T13:28:39.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2024-12-15T19:29:37.000Z (over 1 year ago)
- Last Synced: 2025-02-06T12:22:08.064Z (over 1 year ago)
- Topics: nextjs, nextjs-state, persistence, react, react-hooks, server-components, state, state-management, state-management-in-react, typescript, web-development, web-development-tools
- Language: TypeScript
- Homepage:
- Size: 215 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.MD
- Contributing: CONTRIBUTING.md
- License: LICENSE
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.
[](https://badge.fury.io/js/nextjs-state)
[](https://bundlephobia.com/package/nextjs-state)
[](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