npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

valtio-define

v1.4.0

Published

⚡quickly create a fully functional and robust Valtio factory

Downloads

797

Readme

image

npm version npm downloads bundle JSDocs coverage License.

⚡️ valtio-define is a lightweight factory for creating fully functional, robust Valtio stores. It simplifies state management in React by providing a structured API for state, actions, and computed getters.

📦 Installation

pnpm add valtio valtio-define

You can run npx skills add hairyf/valtio-define --skill valtio-define -y to install the skills!

Remember to ask your owner which Agents need to be supported (using the --agent parameter of skills) to avoid installing too many default agents directories.

🚀 Quick Start

Basic Store

defineStore allows you to encapsulate state and logic in one place. Use useStore to consume the reactive state in your components.

import { defineStore, useStore } from 'valtio-define'

const store = defineStore({
  state: () => ({ count: 0 }),
  actions: {
    increment() {
      // 'this' refers to the reactive state
      this.count++
    },
  },
  getters: {
    doubled() {
      return this.count * 2
    },
  },
})

function Counter() {
  const { count, doubled } = useStore(store)

  return (
    <div>
      <button onClick={store.increment}>Increment</button>
      <div>Count: {count}</div>
      <div>Doubled: {doubled}</div>
    </div>
  )
}

🛠 Advanced Features

The Power of this

Inside actions and getters, this provides full access to the store's state, other actions, and other getters. This type safety across the entire store.

const store = defineStore({
  state: () => ({
    count: 0,
  }),
  actions: {
    // Autocompletion and typings for the whole store ✨
    currentDoubledOne() {
      return this.doublePlusOne
    },
  },
  getters: {
    doubled() {
      return this.count * 2
    },
    // Note: The return type **must** be explicitly set for complex getters
    doublePlusOne() {
      // Access other getters via 'this'
      return this.doubled + 1
    },
  },
})

Persistence

Save and restore your store state using the persist plugin.

  1. Global Registration:

    import valtio from 'valtio-define'
    import { persist } from 'valtio-define/plugins/persist'
    
    valtio.use(persist())
  2. Store Configuration:

    const store = defineStore({
      state: () => ({ count: 0 }),
      persist: {
        key: 'my-app-storage',
        storage: localStorage,
        paths: ['count'], // Optional: Persist specific keys only
      },
    })

    Tip: If you set persist: true, a unique key is automatically generated using structure-id.

Manual Hydration (SSR Friendly)

To avoid hydration mismatches during Server-Side Rendering, disable automatic hydration and rehydrate it in a useEffect.

// Register with hydrate disabled
store.use(persist({ hydrate: false }))

// In your Client Entry / App Root
useEffect(() => {
  store.$persist.rehydrate()
}, [])

React-Idiomatic State Hooks

If you prefer the useState syntax, use storeToState or storeToStates. These return [state, setter] tuples.

function Profile() {
  // Access a single key
  const [name, setName] = storeToState(store, 'name')

  // Access all keys as hooks
  const {
    count: [count, setCount]
  } = storeToStates(store)

  return <input value={name} onChange={e => setName(e.target.value)} />
}

Controlled inputs may lose caret position

Ref: https://github.com/pmndrs/valtio/issues/270

This happens because Valtio batches state updates causing React to re-render after the input event. React resets the DOM value and loses the caret position.

Use { sync: true } to update synchronously and preserve the caret:

function Input() {
  const { text } = useStore(store, { sync: true })
  // const [text, setText] = storeToState(store, 'text', { sync: true })

  return (
    <input
      onChange={e => store.text = e.target.value}
      value={text}
    />
  )
}

🛰 Store API

Every store instance created with defineStore includes built-in utility methods:

  • $patch(obj | fn): Bulk update the state.
  • $subscribe(callback): Watch the entire store for changes.
  • $subscribeKey(key, callback): Watch a specific property.
  • $signal(selector): Render reactive values inline in JSX (works best with the Signal plugin + @jsxImportSource).

📡 Signal

Register the Signal plugin globally:

import valtio from 'valtio-define'
import { signal } from 'valtio-define/plugins/signal'

valtio.use(signal())

Add jsxImportSource at the beginning of your .tsx file:

/** @jsxImportSource valtio-define/plugins/signal */

function App() {
  return <div>{store.$signal(state => state.count)}</div>
}

🔌 Plugins

Global vs. Per-Store

Plugins can be applied to all stores or restricted to a single instance.

import valtio, { defineStore } from 'valtio-define'

// Global
valtio.use(myPlugin())

// Local
const store = defineStore({ /* ... */ })
store.use(myPlugin())

// Local options
const store = defineStore({
  use: [myPlugin()],
})

Creating a Custom Plugin

Extend functionality by accessing the store instance and options through the plugin context.

import type { Plugin } from 'valtio-define'
import valtio from 'valtio-define'

function loggerPlugin(): Plugin {
  return ({ store, options }) => {
    store.$subscribe((state) => {
      console.log('Update:', state)
    })
  }
}

valtio.use(loggerPlugin())

declare module 'valtio-define' {
  export interface StoreDefineOptions<S extends object> {
    $myPlugin?: {
      someOption?: boolean
    }
  }
}

License

MIT License © Hairyf