Quick Start Guide

Get up and running with Mesa in 5 minutes.

This guide will help you build your first Mesa application in just a few minutes. We'll create a simple counter app that demonstrates Mesa's fine-grained reactivity.

Note:

Make sure you've completed the Installation before proceeding.

Your First Mesa App

Let's build a counter application that showcases Mesa's core features:

1
Step 1: Create the State

First, create a proxy state object that will hold our application data:

import { proxy } from "mesa-react";

// Create a global state
const appState = proxy({
  count: 0,
  user: {
    name: "Guest",
    isLoggedIn: false
  }
});
2
Step 2: Create Components

Now, create components that subscribe to specific parts of the state:

import { useStore } from "mesa-react";

function Counter() {
  // Only re-renders when count changes
  const count = useStore(appState, (state) => state.count);

  return (
    <div>
      <h2>Count: {count}</h2>
      <button onClick={() => appState.count++}>
        Increment
      </button>
      <button onClick={() => appState.count--}>
        Decrement
      </button>
      <button onClick={() => appState.count = 0}>
        Reset
      </button>
    </div>
  );
}

function UserProfile() {
  // Only re-renders when user data changes
  const user = useStore(appState, (state) => state.user);

  return (
    <div>
      <h3>User: {user.name}</h3>
      <p>Status: {user.isLoggedIn ? "Logged In" : "Guest"}</p>
    </div>
  );
}
3
Step 3: Compose Your App

Combine the components to create your complete application:

function App() {
  return (
    <div>
      <h1>Mesa Counter App</h1>
      <Counter />
      <UserProfile />

      {/* This button only affects UserProfile, not Counter */}
      <button
        onClick={() => {
          appState.user.name = "John";
          appState.user.isLoggedIn = true;
        }}
      >
        Login as John
      </button>
    </div>
  );
}

export default App;
4
Step 4: Initialize Data

Use useInitSync() to load initial data when your components mount:

import { useInitSync } from "mesa-react";

function Counter() {
  const count = useStore(appState, (state) => state.count);

  // Initialize counter from localStorage
  useInitSync(appState, async (state) => {
    const saved = localStorage.getItem("count");
    if (saved) {
      state.count = parseInt(saved, 10);
    }
  });

  // Save to localStorage when count changes
  React.useEffect(() => {
    localStorage.setItem("count", String(appState.count));
  }, [count]);

  return (
    <div>
      <h2>Count: {count}</h2>
      <button onClick={() => appState.count++}>
        Increment
      </button>
      <button onClick={() => appState.count--}>
        Decrement
      </button>
      <button onClick={() => appState.count = 0}>
        Reset
      </button>
    </div>
  );
}

function UserProfile() {
  const user = useStore(appState, (state) => state.user);

  // Load user data from API
  useInitSync(appState, async (state) => {
    state.user.name = "Loading...";
    try {
      // Simulate API call
      await new Promise(resolve => setTimeout(resolve, 1000));
      const userData = { name: "John Doe", isLoggedIn: true };
      state.user = userData;
    } catch (error) {
      state.user.name = "Error loading user";
    }
  });

  return (
    <div>
      <h3>User: {user.name}</h3>
      <p>Status: {user.isLoggedIn ? "Logged In" : "Guest"}</p>
    </div>
  );
}
5
Step 5: Run Your App

Start your development server and see Mesa in action:

npm run dev
# or
yarn dev
# or
pnpm dev

Try clicking the buttons and notice how only the relevant components re-render! The counter will now persist between page refreshes, and user data loads asynchronously.

Key Concepts Demonstrated

This simple example showcases Mesa's core benefits:

Fine-Grained Updates

  • Clicking "Increment" only re-renders the Counter component
  • Clicking "Login as John" only re-renders the UserProfile component
  • Neither affects the other, even though they share the same state object

Simple API

  • proxy() creates reactive state
  • useStore() subscribes to specific data
  • useInitSync() handles async initialization
  • Direct mutations trigger updates automatically

Async Initialization

  • useInitSync() runs once per store per component tree
  • Supports async operations like API calls and localStorage
  • Maintains loading states and error handling patterns
  • Ensures consistent initialization across your application

Performance

  • Zero unnecessary re-renders
  • Automatic dependency tracking
  • Efficient path-based subscriptions

What's Next?

Now that you've built your first Mesa app, explore these topics:

Note:

🎉 Congratulations! You've successfully created your first Mesa application with fine-grained reactivity.