Skip to content

LocusDagraca/use-better-valtio

Repository files navigation

use-better-valtio

A custom Valtio hook generator that provides Zustand-like developer experience (DX) while leveraging Valtio's reactive state management.

What is this?

This project demonstrates how to create Valtio hooks that feel just like Zustand hooks. You get:

  • ✅ Auto-generated setter functions (setProperty) for each state property
  • ✅ Type-safe custom actions
  • ✅ Same DX as Zustand: const { state, actions } = useStore()
  • ✅ All the benefits of Valtio (proxy-based, performant, React integration)

Quick Start

# Clone and install
git clone <repository-url>
cd use-better-valtio
pnpm install
pnpm dev

Usage Example

import { proxy } from "valtio";
import { createBetterValtioHook } from "./create-better-valtio-hook";

// 1. Define your state interface
interface CounterState {
  count: number;
  label: string;
}

// 2. Create Valtio proxy
const counterStore = proxy<CounterState>({
  count: 0,
  label: ""
});

// 3. Define custom actions (optional)
const customActions = (state: CounterState) => ({
  increment: () => state.count++,
  reset: () => {
    state.count = 0;
    state.label = "";
  }
});

// 4. Create the hook
export const useCounterStore = createBetterValtioHook(
  counterStore,
  customActions
);

// 5. Use it like Zustand!
function CounterComponent() {
  const {
    count,
    label,
    setCount,    // Auto-generated!
    setLabel,    // Auto-generated!
    increment,   // Custom action
    reset        // Custom action
  } = useCounterStore();

  return (
    <div>
      <p>Count: {count}</p>
      <p>Label: {label}</p>
      <button onClick={increment}>+</button>
      <button onClick={() => setCount(count - 1)}>-</button>
      <input
        value={label}
        onChange={(e) => setLabel(e.target.value)}
      />
      <button onClick={reset}>Reset</button>
    </div>
  );
}

Benefits over vanilla Valtio

Before (Vanilla Valtio)

import { useSnapshot } from "valtio";

// Manual state management
const { count, label } = useSnapshot(store);

// Manual mutations
const updateCount = (newCount: number) => {
  store.count = newCount;
};

// No built-in actions pattern

After (use-better-valtio)

// Zustand-like DX with Valtio power
const { count, label, setCount, setLabel } = useStore();

Project Structure

src/
├── valtio/
│   ├── create-better-valtio-hook.ts  # Main hook generator
│   └── example/
│       ├── demo-example.tsx          # Demo component
│       └── use-dummy-store.ts        # Example store implementation
├── main.tsx                         # App entry point

Why not just use Zustand?

Valtio is excellent for nested states. Perfect to deal with structured outputs (json) in AI apps for example.

About

demo on how to use a valtio store with a zustand-like DX

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published