Getting Started
Hello re-state

Hello re-state

This guide will teach you the fundamentals of re-state and help you choose the right approach for your use case.

Installation

npm install @raulpesilva/re-state

or

yarn add @raulpesilva/re-state

Quick Start

re-state offers two main approaches to manage global state:

ApproachBest For
useReStateQuick prototyping, simple states
createReStateMethodsProduction apps, typed states, reusable logic

Approach 1: useReState Hook

The simplest way to share state between components. Works like useState, but the state is global.

import { useReState } from '@raulpesilva/re-state';
 
function Counter() {
  const [count, setCount] = useReState('count', 0);
 
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <button onClick={() => setCount(prev => prev - 1)}>Decrement</button>
    </div>
  );
}

Any component using the same key ('count') will share the same state:

function CounterDisplay() {
  const [count] = useReState('count', 0);
  return <p>Current count: {count}</p>;
}
 
function App() {
  return (
    <div>
      <Counter />
      <CounterDisplay /> {/* Updates when Counter changes */}
    </div>
  );
}

When to use: Quick experiments, simple shared states, or when you want minimal setup.


Approach 2: createReStateMethods (Recommended)

For production apps, createReStateMethods provides a complete, type-safe API with all the utilities you need.

Step 1: Define your state

// states/counter.ts
import { createReStateMethods } from '@raulpesilva/re-state';
 
export const {
  useCounter,        // Hook: [value, setValue]
  useCounterSelect,  // Hook: value only (read-only)
  dispatchCounter,   // Update from anywhere
  getCounter,        // Get value without subscribing
  resetCounter,      // Reset to initial value
} = createReStateMethods('counter', 0);

Step 2: Use in components

// components/Counter.tsx
import { useCounter, resetCounter } from '../states/counter';
 
function Counter() {
  const [count, setCount] = useCounter();
 
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(prev => prev + 1)}>+</button>
      <button onClick={() => setCount(prev => prev - 1)}>-</button>
      <button onClick={resetCounter}>Reset</button>
    </div>
  );
}
// components/CounterDisplay.tsx
import { useCounterSelect } from '../states/counter';
 
function CounterDisplay() {
  const count = useCounterSelect(); // Read-only, simpler API
  return <p>Current count: {count}</p>;
}

When to use: Production applications, when you need type safety, or when you want to update state from outside components.


Working with Complex State

re-state works with any value type: primitives, objects, arrays, or custom types.

Defining typed state

// states/user.ts
import { createReStateMethods } from '@raulpesilva/re-state';
 
interface User {
  id: string;
  name: string;
  email: string;
  avatar: string;
}
 
const initialUser: User = {
  id: '',
  name: '',
  email: '',
  avatar: '',
};
 
export const {
  useUser,
  useUserSelect,
  dispatchUser,
  getUser,
  resetUser,
} = createReStateMethods('user', initialUser);

Using object state

import { useUser } from '../states/user';
 
function UserProfile() {
  const [user, setUser] = useUser();
 
  return (
    <div>
      <img src={user.avatar} alt={user.name} />
      <h1>{user.name}</h1>
      <p>{user.email}</p>
      <button
        onClick={() =>
          setUser({
            id: '123',
            name: 'John Doe',
            email: 'john@example.com',
            avatar: 'https://example.com/avatar.png',
          })
        }
      >
        Set User
      </button>
    </div>
  );
}

Updating partial state

Use the callback form to update only specific fields:

import { useUser } from '../states/user';
 
function EditName() {
  const [user, setUser] = useUser();
 
  const updateName = (name: string) => {
    setUser(prev => ({ ...prev, name }));
  };
 
  return (
    <input
      value={user.name}
      onChange={e => updateName(e.target.value)}
      placeholder="Enter name"
    />
  );
}

Creating Actions

For reusable logic, define actions alongside your state:

// states/user.ts
import { createReStateMethods } from '@raulpesilva/re-state';
 
interface User {
  id: string;
  name: string;
  email: string;
}
 
const initialUser: User = { id: '', name: '', email: '' };
 
export const {
  useUser,
  useUserSelect,
  dispatchUser,
  getUser,
  resetUser,
} = createReStateMethods('user', initialUser);
 
// Custom actions
export const updateName = (name: string) => {
  dispatchUser(prev => ({ ...prev, name }));
};
 
export const updateEmail = (email: string) => {
  dispatchUser(prev => ({ ...prev, email }));
};
 
export const fetchUser = async (userId: string) => {
  const response = await fetch(`/api/users/${userId}`);
  const user = await response.json();
  dispatchUser(user);
};

Use actions in your components:

import { useUserSelect, updateName, fetchUser, resetUser } from '../states/user';
import { useEffect } from 'react';
 
function UserProfile({ userId }: { userId: string }) {
  const user = useUserSelect();
 
  useEffect(() => {
    fetchUser(userId);
  }, [userId]);
 
  return (
    <div>
      <h1>{user.name}</h1>
      <button onClick={() => updateName('New Name')}>Change Name</button>
      <button onClick={resetUser}>Logout</button>
    </div>
  );
}

Updating State Outside React

Use dispatch* and get* to work with state outside of React components:

import { dispatchCounter, getCounter } from '../states/counter';
 
// In an event handler
document.addEventListener('keydown', (event) => {
  if (event.key === 'ArrowUp') {
    dispatchCounter(prev => prev + 1);
  }
  if (event.key === 'ArrowDown') {
    dispatchCounter(prev => prev - 1);
  }
});
 
// In a utility function
function logCurrentCount() {
  console.log('Current count:', getCounter());
}
 
// In an async function
async function syncWithServer() {
  const count = getCounter();
  await fetch('/api/count', {
    method: 'POST',
    body: JSON.stringify({ count }),
  });
}

Available APIs

Here's a quick reference of all re-state methods:

Hooks

MethodDescription
useReStateSimple hook with key and initial value
useReStateSelectorSubscribe to state with a selector function

Factory Functions

MethodDescription
createReStateMethodsCreates all methods at once (recommended)
createReStateCreates a typed hook for a key
createReStateSelectCreates a read-only hook
createReStateDispatchCreates a dispatch function
createGetReStateCreates a getter function

Utilities

MethodDescription
onReStateChangeSubscribe to state changes outside React
resetReStateReset a state to its initial value
setReStateInitialValueSet the initial value for a key

Next Steps