API: store.get()
The store.get() method provides a direct way to access the current state of a SoulState store. It is used for non-reactive reads, typically outside of React components or within actions where you need a snapshot of the current state without triggering re-renders.
Summary
store.get() returns the current state object held by the store. It is a synchronous, non-reactive operation.
Function Signature
interface Store<T> {
get: () => T;
// ... other methods
}
Parameters
None.
Return Value
T: The current state object of the store.
Usage Examples
Basic Usage: Reading State Outside React
You can call get() directly on your store instance to get its current value.
import { counterStore } from '../stores/counterStore';
// Get the entire state
const currentState = counterStore.get();
console.log('Current state:', currentState);
// Get specific property
const currentCount = counterStore.get().count;
console.log('Current count:', currentCount);
Advanced Usage: Within Actions
get() is often used within actions to derive new state based on the current state.
import { createStore } from 'soulstate';
// Create store
export const todoStore = createStore({
todos: []
});
// Define actions that use store.get()
export const todoActions = {
addTodo: (text: string) => {
todoStore.set(state => ({
todos: [...state.todos, { id: Date.now(), text, completed: false }]
}));
},
toggleAll: () => {
// Use get() to read current state non-reactively
const currentTodos = todoStore.get().todos;
const allCompleted = currentTodos.every(todo => todo.completed);
todoStore.set(state => ({
todos: state.todos.map(todo => ({
...todo,
completed: !allCompleted
}))
}));
},
getCompletedCount: () => {
// Utility function using get()
return todoStore.get().todos.filter(todo => todo.completed).length;
}
};
Usage in Event Handlers
import { counterStore, counterActions } from '../stores/counterStore';
function SomeComponent() {
const handleComplexAction = () => {
// Read current state in event handler
const currentCount = counterStore.get().count;
if (currentCount > 10) {
console.log('Count is already high:', currentCount);
return;
}
// Perform multiple updates
counterActions.increment();
counterActions.increment();
// Verify the final state
console.log('Final count:', counterStore.get().count);
};
return (
<button onClick={handleComplexAction}>
Complex Action
</button>
);
}
Anti-patterns
1. Using get() for Reactive UI Updates
Never use store.get() directly in a React component's render logic if you expect the component to re-render when the state changes. get() is non-reactive. For reactive updates, always use the useStore hook.
// ❌ Anti-pattern: This component will NOT update when count changes
function BadCounter() {
const count = counterStore.get().count; // Stale value after updates
return <div>Count: {count}</div>;
}
// ✅ Correct: Use useStore hook for reactive updates
import { useStore } from 'soulstate/react';
function GoodCounter() {
const count = useStore(counterStore, state => state.count);
return <div>Count: {count}</div>;
}
2. Using get() Instead of Functional Updates
Avoid using get() when a functional update would be more appropriate.
// ❌ Less optimal: Multiple store interactions
const increment = () => {
const current = counterStore.get().count;
counterStore.set({ count: current + 1 });
};
// ✅ Better: Single atomic update with functional set
const increment = () => {
counterStore.set(state => ({ count: state.count + 1 }));
};
Performance Notes
store.get() is an extremely fast, O(1) operation. It simply returns a reference to the current state object. It involves:
- ✅ No subscriptions
- ✅ No change detection
- ✅ No equality checks
- ✅ No re-renders
Common Use Cases
Logging and Debugging
// Useful for debugging state changes
const logState = () => {
console.log('Current store state:', counterStore.get());
};
// Or in development
if (process.env.NODE_ENV === 'development') {
window.getStoreState = () => counterStore.get();
}
Conditional Logic in Actions
export const authActions = {
login: (credentials: any) => {
// Check current state before proceeding
if (authStore.get().isLoading) {
console.log('Already loading, skipping...');
return;
}
authStore.set({ isLoading: true });
// ... login logic
}
};
Integration with Non-React Code
// Using SoulState stores in vanilla JS
document.getElementById('save-btn').addEventListener('click', () => {
const currentData = formStore.get();
saveToLocalStorage('form-data', currentData);
});
// In Node.js scripts
const currentConfig = configStore.get();
generateReport(currentConfig);
Best Practices
✅ Do:
- Use
get()for one-off reads in event handlers - Use
get()in actions for conditional logic - Use
get()for debugging and logging - Use
get()when integrating with non-React code
❌ Don't:
- Use
get()for reactive UI updates - Call
get()excessively in performance-critical loops - Use
get()when functionalset()would suffice - Forget that
get()returns stale data in async contexts
Async Context Warning
In asynchronous code, the state returned by get() might be stale if other updates occur before your async operation completes. For async scenarios, consider storing the needed values in local variables before the async call.
Key Takeaway
store.get() is your tool for non-reactive state access. Use it for reading current state in actions, event handlers, and non-React code. For any data that should update your UI reactively, always use useStore.