Skip to main content

Migration Guide

This guide helps you migrate from other state management libraries to SoulState.

From Zustand

SoulState provides a Zustand-compatible API. Most code requires minimal changes.

Basic Store

Zustand:

import { create } from 'zustand';

const useStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}));

SoulState:

import { createStore } from 'soulstate';

const store = createStore({
count: 0,
});

const actions = {
increment: () => store.setState(s => ({ count: s.count + 1 })),
};

Subscriptions

Zustand:

const unsubscribe = useStore.subscribe(
(state) => state.count,
(count) => console.log('Count:', count)
);

SoulState:

const unsubscribe = store.subscribe(
(state) => state.count,
(count) => console.log('Count:', count)
);

Computed Values

Zustand: Uses external libraries or manual implementation.

SoulState: Built-in computed support:

const doubleCount = store.computed((state) => state.count * 2);

Key Differences

FeatureZustandSoulState
Granular UpdatesManual selector optimizationAutomatic fine-grained reactivity
Computed ValuesExternal libraryBuilt-in
Glitch-FreeNot guaranteedGuaranteed
Batch UpdatesManual batchingAutomatic microtask batching

From Redux/Redux Toolkit

Store Setup

Redux Toolkit:

import { configureStore, createSlice } from '@reduxjs/toolkit';

const counterSlice = createSlice({
name: 'counter',
initialState: { count: 0 },
reducers: {
increment: (state) => { state.count += 1; },
},
});

const store = configureStore({
reducer: { counter: counterSlice.reducer },
});

SoulState:

import { createStore } from 'soulstate';

const store = createStore({
count: 0,
});

const actions = {
increment: () => store.setState(s => ({ count: s.count + 1 })),
};

Dispatching Actions

Redux:

store.dispatch(counterSlice.actions.increment());

SoulState:

store.getState().increment();
// or
store.setState((state) => ({ count: state.count + 1 }));

Selectors

Redux:

const count = useSelector((state) => state.counter.count);

SoulState:

const count = useStore(store, (state) => state.count);

Key Differences

FeatureReduxSoulState
BoilerplateReducers, actions, dispatchMinimal
ImmutabilityManual or ImmerStructural sharing
PerformanceO(N) global updatesO(M) surgical updates
DevToolsRedux DevToolsRedux DevTools compatible

From Jotai

Atom Creation

Jotai:

import { atom, useAtom } from 'jotai';

const countAtom = atom(0);
const doubleAtom = atom((get) => get(countAtom) * 2);

SoulState:

import { createStore } from 'soulstate';

const store = createStore({
count: 0,
});

const doubleCount = store.computed((state) => state.count * 2);

Usage in React

Jotai:

function Counter() {
const [count, setCount] = useAtom(countAtom);
return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

SoulState:

function Counter() {
const count = useStore(store, (state) => state.count);
return (
<button onClick={() => store.getState().increment()}>
{count}
</button>
);
}

Key Differences

FeatureJotaiSoulState
State OrganizationDecentralized atomsCentralized store
DependenciesAutomatic via readsAutomatic via tracking
PerformanceGood at small scaleExcellent at large scale
Mental ModelAtomicGraph-based

From Valtio

Proxy Creation

Valtio:

import { proxy, useSnapshot } from 'valtio';

const state = proxy({ count: 0 });

function Counter() {
const snap = useSnapshot(state);
return <button onClick={() => { state.count += 1; }}>{snap.count}</button>;
}

SoulState:

import { createStore } from 'soulstate';

const store = createStore({
count: 0,
});

const actions = {
increment: () => store.setState(s => ({ count: s.count + 1 })),
};

function Counter() {
const count = useStore(store, (state) => state.count);
return (
<button onClick={actions.increment}>
{count}
</button>
);
}

Key Differences

FeatureValtioSoulState
Mutation ModelDirect mutationImmutable updates
TrackingProxy-basedProxy-based
PerformanceGoodExcellent
TypeScriptLimited inferenceFull type inference

General Migration Checklist

  1. Install SoulState:

    npm install soulstate
  2. Replace store creation:

    • Remove old store setup
    • Create new SoulState store with createStore
  3. Update state access:

    • Replace direct state access with store.getState()
    • Update subscriptions to use SoulState API
  4. Add computed values:

    • Convert derived state to store.computed()
    • Replace manual memoization
  5. Update React components:

    • Replace useSelector with useStore
    • Update dispatch calls to use store actions
  6. Test thoroughly:

    • Verify all state updates work
    • Check subscription cleanup
    • Validate computed value caching

Need Help?