relat
v0.1.0
Published
State manager for react
Readme
React State Manager Documentation
Overview
relat is a lightweight state management solution for React applications that uses JavaScript Proxies for automatic reactivity. It provides a simple API for creating global state containers that trigger re-renders when their properties change.
Key advantages:
- 🚀 Zero-boilerplate state management
- ⚡ Automatic dependency tracking
- 🔥 Direct mutation API (no reducers/dispatchers)
- 📦 <1KB minified (no dependencies)
- 💡 Perfect for small-to-medium apps
Ideal for:
- Developers who want simple global state
- Projects needing Reactivity API similar to Vue
- Teams migrating from useState/useContext
Installation
npm install relat
# or
yarn add relatInitialization
Initialize in your app entry point (e.g., index.js):
// index.js
import { initFull } from 'relat';
import React from 'react';
initFull({
useState: React.useState,
useRef: React.useRef,
useEffect: React.useEffect
});Basic Usage
- Define state container
// store.js
import { defineFull } from 'relat';
export const counterState = defineFull({
count: 0,
increment() {
this.count++;
}
});- Use in components
// Counter.jsx
import { useFull } from 'relat';
import { counterState } from './store';
function Counter() {
const state = useFull(counterState);
return (
<div>
<p>Count: {state.count}</p>
<button onClick={state.increment}>+1</button>
</div>
);
}Advanced Example
// authStore.js
import { defineFull } from 'relat';
export const authState = defineFull(() => ({
user: null,
isLoggedIn: false,
login(email, password) {
// Mock API call
setTimeout(() => {
this.user = { email, name: "John Doe" };
this.isLoggedIn = true;
}, 300);
},
logout() {
this.user = null;
this.isLoggedIn = false;
}
}));// AuthComponent.jsx
import { useFull } from 'relat';
import { authState } from './authStore';
function AuthComponent() {
const { user, isLoggedIn, login, logout } = useFull(authState);
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
if (isLoggedIn) {
return (
<div>
<h1>Welcome, {user.name}!</h1>
<button onClick={logout}>Logout</button>
</div>
);
}
return (
<form onSubmit={() => login(email, password)}>
<input
type="email"
value={email}
onChange={e => setEmail(e.target.value)}
/>
<input
type="password"
value={password}
onChange={e => setPassword(e.target.value)}
/>
<button type="submit">Login</button>
</form>
);
}API Reference
initFull(options)
Initializes the state manager with React hooks
Parameters:
options: Configuration objectuseState: React's useState hookuseRef: React's useRef hookuseEffect: React's useEffect hook
Example:
initFull({
useState: React.useState,
useRef: React.useRef,
useEffect: React.useEffect
});defineFull(defaults)
Creates a state container
Parameters:
defaults: Initial state (object or factory function)
Returns:
State key (used with useFull)
Example:
const store = defineFull({
counter: 0,
todos: []
});
// With factory function
const configStore = defineFull(() => ({
theme: 'dark',
language: 'en'
}));useFull(dataKey)
Hook for accessing state
Parameters:
dataKey: Key from defineFull
Returns:
Proxy object with your state
Example:
const state = useFull(store);
state.counter = 5; // Triggers re-renderSpecial Properties
__versionSymbol: Read-only version counter
console.log(state[__versionSymbol]); // 0,1,2...Performance Notes
- For large state objects, avoid frequent top-level mutations
- Use nested objects carefully (shallow changes only trigger updates)
- Batch related changes:
// Instead of:
state.a = 1;
state.b = 2;
// Do:
Object.assign(state, { a: 1, b: 2 });Testing
Use included test utilities:
import { render, screen } from '@testing-library/react';
import { defineFull, useFull } from 'relat';
test('state updates', async () => {
const store = defineFull({ count: 0 });
function TestComponent() {
const state = useFull(store);
return <div onClick={() => state.count++}>{state.count}</div>;
}
render(<TestComponent />);
await userEvent.click(screen.getByText('0'));
expect(screen.getByText('1')).toBeInTheDocument();
});