Skip to main content

Troubleshooting Guide

Common issues and solutions when using SoulState.

Installation Issues

Module not found

Error:

Module not found: Can't resolve 'soulstate'

Solution:

npm install soulstate
# or
yarn add soulstate
# or
pnpm add soulstate

TypeScript errors

Error:

Cannot find module 'soulstate' or its corresponding type declarations.

Solution: Ensure you have the latest version and TypeScript is configured correctly:

npm install soulstate@latest
npm install -D typescript@latest

Store Creation Issues

Store not reactive

Symptom: State changes don't trigger re-renders.

Solution: Ensure you're using the store hook correctly:

// Wrong - accessing state directly
const count = store.getState().count;

// Correct - using useStore hook
const count = useStore(store, (state) => state.count);

Multiple stores conflict

Symptom: Updates to one store affect another.

Solution: Each store is independent. Ensure you're using the correct store instance:

const storeA = createStore({ a: 1 });
const storeB = createStore({ b: 2 });

// Each store is separate
useStore(storeA, (state) => state.a);
useStore(storeB, (state) => state.b);

Subscription Issues

Subscription not firing

Symptom: Listener doesn't execute when state changes.

Solution:

  1. Check the selector function:

    // Wrong - selector returns same reference
    store.subscribe(
    (state) => state, // Always returns same object
    (state) => console.log(state)
    );

    // Correct - selector returns specific value
    store.subscribe(
    (state) => state.count,
    (count) => console.log(count)
    );
  2. Verify the subscription is active:

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

    // Subscription is active until unsubscribed
    unsubscribe(); // Now it's inactive

Memory leak from subscriptions

Symptom: Memory usage grows over time.

Solution: Always unsubscribe when component unmounts:

useEffect(() => {
const unsubscribe = store.subscribe(
(state) => state.count,
(count) => console.log(count)
);

return () => unsubscribe(); // Cleanup on unmount
}, []);

Computed Value Issues

Computed not updating

Symptom: Computed value doesn't reflect changes.

Solution: Ensure computed is accessing the correct state:

// Wrong - computed not accessing state
const double = store.computed(() => 2); // Static value

// Correct - computed accessing state
const double = store.computed((state) => state.count * 2);

Computed re-computing too often

Symptom: Computed function runs excessively.

Solution: SoulState caches computed values. If it's re-computing, check:

  1. Dependencies are changing
  2. Selector is deterministic
  3. No external state is being accessed

Performance Issues

Slow updates with many subscribers

Symptom: Updates are slow with 1000+ subscribers.

Solution: Use surgical selectors:

// Wrong - triggers all subscribers
store.subscribe(
(state) => state, // Returns entire state
(state) => { /* ... */ }
);

// Correct - triggers only relevant subscribers
store.subscribe(
(state) => state.specificKey, // Returns only what you need
(value) => { /* ... */ }
);

Unnecessary re-renders

Symptom: Components re-render when they shouldn't.

Solution: Use shallow equality for object selections:

import { shallow } from 'soulstate/utils';

useStore(
store,
(state) => ({ a: state.a, b: state.b }),
shallow // Prevents re-render if a and b haven't changed
);

React Integration Issues

useStore not working

Symptom: useStore hook throws error.

Solution: Ensure you're using the correct import:

// Wrong
import { useStore } from 'soulstate';

// Correct
import { useStore } from 'soulstate/react';

Provider not found

Symptom: Error about missing context provider.

Solution: Wrap your app with the Provider:

import { Provider } from 'soulstate/react';

function App() {
return (
<Provider store={store}>
<MyComponent />
</Provider>
);
}

Transaction Issues

Transaction not batching

Symptom: Updates happen immediately instead of batching.

Solution: Use the transaction API:

store.beginTransaction();
store.setState({ count: 1 });
store.setState({ name: 'updated' });
// Both updates happen atomically
store.commitTransaction();

Transaction rollback not working

Symptom: State changes persist after rollback.

Solution: Ensure you're in a transaction:

store.beginTransaction();

try {
store.setState({ count: 1 });
store.setState({ count: 2 });
store.rollbackTransaction(); // Reverts to state before transaction
} catch (error) {
store.rollbackTransaction();
}

Debugging Tips

Enable instrumentation

store.enableInstrumentation({
onFlush: (duration, keys) => {
console.log('Flush duration:', duration);
},
onSelectorRun: (name, duration) => {
console.log('Selector:', String(name), 'took', duration, 'ms');
}
});

// Access metrics
const metrics = store.getMetrics();
if (metrics) {
console.log('Average Flush Time:', metrics.averageFlushDuration);
console.log('Selector Runs:', metrics.selectorRunCount);
}

Check store state

// Current state
console.log(store.getState());

// Previous state (during update)
store.subscribe(
(state) => state.count,
(count, prevCount) => {
console.log('Updated from', prevCount, 'to', count);
}
);

Still Stuck?