Skip to content

Getting Started with neutrix

Installation

Add neutrix to your project:

bash
npm install neutrix

Setup for Typescript configuration

To use neutrix with TypeScript, ensure your tsconfig.json has the following configurations:

json
{
  "compilerOptions": {
    "target": "ESNext",
    "moduleResolution": "node",
    "jsx": "react-jsx",
    "esModuleInterop": true,
    "strict": true,
    "skipLibCheck": true
  }
}

Core Features Overview

neutrix is a state management library providing the following core capabilities:

Core Neutrix Flow

Store Management

  • State creation and configuration
  • Immutable updates
  • Batch operations
  • Path-based access

Advanced Features

  • Computed values with LRU caching
  • Suspense support
  • Store connections
  • Middleware system
  • Path optimization
  • DevTools integration
  • State persistence and migration

React Integration

  • Provider system (optional)
  • Custom hooks
  • Action handling

Core Concepts

Creating a Store

Neutrix provides multiple ways to create a store. createNeutrixStore is the recommended and most flexible approach:

typescript
// You can choose either approach depending on your app’s scale

import { createNeutrixStore } from 'neutrix';

// Hook-based store (simpler)
const useStore = createNeutrixStore({ count: 0 });

// Provider-based store
const { store, useStore, Provider } = createNeutrixStore(
  { count: 0 }, 
  { provider: true }
);

Store options

All store creators accept these options:

typescript
interface StoreOptions {
  name?: string;           // Store name for DevTools/persistence
  devTools?: boolean;      // Enable Redux DevTools
  persist?: boolean | ((state: any) => any); // Enable localStorage persistence
  validate?: (state: State) => boolean | string; // Add validation
  migration?: {            // Handle persistence migrations
    version: number;
    migrate: (oldState: any) => any;
  };
  concurrency?: boolean; // Enable React concurrenct (e.g., startTransition)
  onDestroy?: () => void;    // Enable React concurrency features
}

State Operations

You can access state in two ways:

typescript
// 1. Direct property access (recommended and simpler way too)
const count = useStore(s => s.count);

// 2. Path-based access
const count = useStore(s => s.get('count'));

Updating state:

typescript
// 1. Using store.set
useStore.store.set('count', count + 1);

// 2. Batch updates
useStore.store.batch([
  ['count', newCount],
  ['lastUpdated', Date.now()]
]);

Computed Values

Computed values are derived state that update automatically when dependencies change:

typescript
import { useNeutrixComputed } from 'neutrix';

const fullName = useNeutrixComputed(store => {
  const firstName = store.get('user.firstName');
  const lastName = store.get('user.lastName');
  return `${firstName} ${lastName}`;
});

Async actions

typescript
// 1. define in the initial state
const useStore = createNeutrixStore({
  count: 0,
  increment: async (state) => {
    await someAsyncOperation();
    return { count: state.count + 1 };
  }
});

// 2. use useNeutrixAction hook
import { useNeutrixAction } from 'neutrix';

const { loading, error, execute } = useNeutrixAction(
  async (store) => {
    await someAsyncOperation();
    store.set('count', store.get('count') + 1);
  }
);

Middleware

Middleware lets you intercept and transform state operations:

typescript
useStore.store.use({
  onSet: (path, value, prevValue) => {
    console.log(`Set: ${path} from ${prevValue} to ${value}`);
    return value;
  },
  onGet: (path, value) => {
    console.log(`Get: ${path} -> ${value}`);
    return value;
  },
  onError: (error) => {
    console.error('Store error:', error);
  }
});

Suspense Support

Handle async data loading with React Suspense:

Features:

  • Cache promise results
  • Automatic promise tracking

Store patterns

1. Single store (no provider)

typescript
import { createNeutrixStore } from 'neutrix';

// simplest approach
const useStore = createNeutrixStore({ count: 0 });

function Counter() {
  const count = useStore(s => s.count);
  return <div>{count}</div>;
}

2. Single store (with provider)

typescript
import { createNeutrixStore } from 'neutrix';

const { Provider, useStore } = createNeutrixStore(
  { count: 0 },
  { provider: true }
);

function App() {
  return (
    <Provider>
      <Counter />
    </Provider>
  );
}

3. Multiple stores

typescript
import { createNeutrixStore, NeutrixProvider } from 'neutrix';

const { store: userStore } = createNeutrixStore({ user: null }, { provider: true });
const { store: cartStore } = createNeutrixStore({ items: [] }, { provider: true });

function App() {
  return (
    <NeutrixProvider stores={{ userStore, cartStore }}>
      <YourApp />
    </NeutrixProvider>
  );
}

Advanced features

Batch Updates

Optimize performance by batching multiple updates:

typescript
useStore.store.batch([
  ['user.name', 'John'],
  ['user.lastLogin', Date.now()],
  ['user.status', 'active']
]);

Dependency Tracking

Neutrix automatically tracks which parts of the state each component uses and only re-renders when those specific parts change:

typescript
// this component will only re-render when user.firstName or user.lastName change
function UserGreeting() {
  const fullName = useNeutrixComputed(store => {
    return `${store.user.firstName} ${store.user.lastName}`;
  });
  return <h1>Hello, {fullName}!</h1>;
}

Technical Details

The library provides these core types:

  • Store<T>: Main store interface
  • State: Base state type
  • Middleware: Middleware interface
  • StoreOptions: Store configuration
  • BatchUpdate: Batch update type

Type references

typescript
interface StoreOptions {
  name?: string;
  devTools?: boolean;
  persist?: boolean | ((state: any) => any);
  validate?: (state: State) => boolean | string;
  migration?: {
    version: number;
    migrate: (oldState: any) => any;
  };
  concurrenct?: boolean; // <--- updated to match code
  onDestroy?: () => void;
}

Next Steps