React Integration
QuantaJS provides seamless React integration through the @quantajs/react package, offering hooks, components, and utilities designed specifically for React applications.
Installation
First, install both the core and React packages:
npm install @quantajs/react @quantajs/core
# or
yarn add @quantajs/react @quantajs/core
# or
pnpm add @quantajs/react @quantajs/core
Basic Setup
Provider Pattern
Wrap your app with QuantaProvider to provide stores to all child components. The stores prop accepts an object where keys are store names and values are store instances:
import { createStore, QuantaProvider, useStore } from '@quantajs/react';
const counterStore = createStore('counter', {
state: () => ({ count: 0 }),
getters: {
doubleCount: (state) => state.count * 2,
},
actions: {
increment() { this.count++; },
decrement() { this.count--; },
},
});
function Counter() {
const store = useStore('counter');
return (
<div>
<p>Count: {store.count}</p>
<p>Double: {store.doubleCount}</p>
<button onClick={() => store.increment()}>+</button>
<button onClick={() => store.decrement()}>-</button>
</div>
);
}
function App() {
return (
<QuantaProvider stores={{ counter: counterStore }}>
<Counter />
</QuantaProvider>
);
}
Hooks
useStore
Access a store from the nearest QuantaProvider by providing the store name. Optionally, you can provide a selector function to pick specific parts of the store:
import { useStore } from '@quantajs/react';
function UserProfile() {
// Access entire store
const store = useStore('user');
return (
<div>
<h1>{store.user.name}</h1>
<p>Email: {store.user.email}</p>
<button onClick={() => store.updateProfile({ name: 'New Name' })}>
Update Name
</button>
</div>
);
}
function UserName() {
// Use selector to only re-render when name changes
const name = useStore('user', store => store.user?.name);
return <h1>{name || 'Guest'}</h1>;
}
useQuantaStore
Subscribe to a specific store with optional selector for performance:
import { useQuantaStore } from '@quantajs/react';
function TodoList() {
// Subscribe to the entire store
const store = useQuantaStore(todoStore);
return (
<ul>
{store.todos.map(todo => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
);
}
function TodoCount() {
// Only re-render when count changes
const count = useQuantaStore(todoStore, store => store.todos.length);
return <p>Total todos: {count}</p>;
}
function CompletedCount() {
// Only re-render when completed count changes
const completed = useQuantaStore(todoStore, store =>
store.todos.filter(todo => todo.done).length
);
return <p>Completed: {completed}</p>;
}
useCreateStore
Create a component-scoped store that's automatically cleaned up:
import { useCreateStore } from '@quantajs/react';
function TodoComponent() {
const todoStore = useCreateStore(
'todos',
() => ({ todos: [] }),
undefined,
{
addTodo(text) {
this.todos.push({ id: Date.now(), text, done: false });
},
toggleTodo(id) {
const todo = this.todos.find(t => t.id === id);
if (todo) todo.done = !todo.done;
},
}
);
return (
<div>
<button onClick={() => todoStore.addTodo('New task')}>
Add Todo
</button>
<p>Todos: {todoStore.todos.length}</p>
<ul>
{todoStore.todos.map(todo => (
<li
key={todo.id}
onClick={() => todoStore.toggleTodo(todo.id)}
style={{ textDecoration: todo.done ? 'line-through' : 'none' }}
>
{todo.text}
</li>
))}
</ul>
</div>
);
}
Advanced Patterns
Multiple Stores
You can provide multiple stores to QuantaProvider using the stores prop object:
import { createStore, QuantaProvider, useStore } from '@quantajs/react';
const userStore = createStore('user', {
state: () => ({ user: null, isLoading: false }),
actions: {
async login(credentials) {
this.isLoading = true;
// API call...
this.user = userData;
this.isLoading = false;
},
},
});
const todoStore = createStore('todos', {
state: () => ({ todos: [] }),
actions: {
addTodo(text) {
this.todos.push({ id: Date.now(), text, done: false });
},
},
});
function App() {
return (
<QuantaProvider stores={{ user: userStore, todos: todoStore }}>
<UserDashboard />
</QuantaProvider>
);
}
function UserDashboard() {
const userStore = useStore('user');
const todoStore = useStore('todos');
return (
<div>
<UserInfo />
<TodoList />
</div>
);
}
Custom Hooks
Create custom hooks to encapsulate store logic:
function useUser() {
const store = useStore('user');
return {
user: store.user,
isLoading: store.isLoading,
login: store.login,
logout: store.logout,
isAuthenticated: !!store.user,
};
}
function useTodos() {
const store = useStore('todos');
return {
todos: store.todos,
addTodo: store.addTodo,
toggleTodo: store.toggleTodo,
removeTodo: store.removeTodo,
completedCount: store.todos.filter(t => t.done).length,
};
}
function UserProfile() {
const { user, isAuthenticated, login } = useUser();
if (!isAuthenticated) {
return <LoginForm onLogin={login} />;
}
return (
<div>
<h1>{user.name}</h1>
<TodoManager />
</div>
);
}
function TodoManager() {
const { todos, addTodo, completedCount } = useTodos();
return (
<div>
<p>Completed: {completedCount}/{todos.length}</p>
<AddTodoForm onAdd={addTodo} />
<TodoList todos={todos} />
</div>
);
}
Performance Optimization
Use selectors to prevent unnecessary re-renders:
function ExpensiveComponent() {
// Only re-render when specific values change
const expensiveValue = useQuantaStore(store, store =>
store.items
.filter(item => item.active)
.map(item => item.value)
.reduce((sum, val) => sum + val, 0)
);
return <div>Expensive calculation: {expensiveValue}</div>;
}
function OptimizedList() {
// Only re-render when the array length changes
const itemCount = useQuantaStore(store, store => store.items.length);
return (
<div>
<p>Total items: {itemCount}</p>
<ItemList />
</div>
);
}
function ItemList() {
// Only re-render when items change
const items = useQuantaStore(store, store => store.items);
return (
<ul>
{items.map(item => (
<Item key={item.id} item={item} />
))}
</ul>
);
}
TypeScript Support
Full TypeScript support with proper type inference:
interface UserState {
user: User | null;
isLoading: boolean;
}
interface UserGetters {
isAuthenticated: boolean;
}
interface UserActions {
login(credentials: LoginCredentials): Promise<void>;
logout(): void;
}
const userStore = createStore<UserState, UserGetters, UserActions>('user', {
state: () => ({ user: null, isLoading: false }),
getters: {
isAuthenticated: (state) => !!state.user,
},
actions: {
async login(credentials) {
this.isLoading = true;
// API call...
this.user = userData;
this.isLoading = false;
},
logout() {
this.user = null;
},
},
});
function UserComponent() {
const store = useStore('user'); // Fully typed!
return (
<div>
{store.isAuthenticated ? (
<p>Welcome, {store.user!.name}</p>
) : (
<LoginForm />
)}
</div>
);
}
DevTools Integration
QuantaJS DevTools provide a powerful debugging interface for inspecting stores and monitoring state changes. In React applications, you can use the QuantaDevTools component:
import { QuantaDevTools } from '@quantajs/react';
function App() {
return (
<QuantaProvider stores={{ user: userStore, todos: todoStore }}>
<YourApp />
<QuantaDevTools />
</QuantaProvider>
);
}
The QuantaDevTools component automatically:
- Detects the development environment
- Connects to all stores in your
QuantaProvider - Provides real-time state inspection
- Logs all actions with timestamps and payloads
DevTools Features
- Store Inspector: View live state, getters, and actions for each store
- Action Log: Track all state mutations with timestamps
- Persistence Management: View and manage persistence status
- Search: Quickly find stores by name
For more information, see the DevTools Guide.
Best Practices
Store Organization
- Keep stores focused on specific domains
- Use descriptive store names
- Group related state, getters, and actions together
Performance
- Use selectors with
useQuantaStorefor fine-grained updates - Avoid watching entire large objects
- Use
useCreateStorefor component-scoped state
Error Handling
- Handle async actions properly with loading states
- Provide fallback values for computed properties
- Use TypeScript for better error catching
Learn More
- Core Concepts - Understanding reactivity
- Managing Stores - Store management patterns
- DevTools Guide - Debugging with DevTools
- API Reference - Complete API documentation