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

@frostime/solid-signal-ref

v2.2.0

Published

A utility for SolidJS, to make it easier to manage signals in components

Readme

@frostime/solid-signal-ref

中文文档

A tiny utility to make using SolidJS signals and stores more ergonomic.
It provides a Vue-like “ref” style API while still being fully Solid-native.

Installation

npm install @frostime/solid-signal-ref

Exports

import {
  // signals
  useSignalRef,
  createSignalRef,
  wrapSignalRef,
  type ISignalRef,

  // stores
  useStoreRef,
  createStoreRef,
  wrapStoreRef,
  type IStoreRef,
} from '@frostime/solid-signal-ref';
  • useSignalRef / createSignalRef – create a ref from an initial value (wraps createSignal)
  • wrapSignalRef – wrap an existing Accessor + Setter into a ref
  • useStoreRef / createStoreRef – create a ref from an initial object (wraps createStore)
  • wrapStoreRef – wrap an existing Store + SetStoreFunction into a ref

Signal Ref (useSignalRef)

Basic usage

Import and create a ref:

import { useSignalRef } from '@frostime/solid-signal-ref';

const count = useSignalRef<number>(0);

Reading the value

count();        // Accessor style
count.value;    // Vue style
count.signal(); // The underlying Solid accessor (same as signal())

Updating the value

count(1);          // Setter style
count.value = 2;   // Vue style
count.update(3);   // Directly call the underlying setter
count.update(v => v * 2); // Functional update

Derived signals

derived creates a memoized accessor (Accessor<R>):

// Equivalent to: const doubled = () => count() * 2;
const doubled = count.derived(c => c * 2);

<p>Doubled count: {doubled()}</p>

Unwrapped value

unwrap returns the current value with Solid’s unwrap applied. For primitive values it’s just the current value; for nested stores it will remove Solid’s proxies.

const value = count.unwrap();

Full example

import { useSignalRef } from '@frostime/solid-signal-ref';
import { createMemo } from 'solid-js';

function App() {
  const count = useSignalRef(0);

  const odd = () => (count() % 2 === 1 ? 'Yes' : 'No');
  const wordCount = count.derived(c => `Word count: ${c.toString().length}`);

  const numberStr = createMemo(() => {
    const abs = Math.abs(count());
    if (abs < 1000) return abs.toString();
    if (abs < 1_000_000) return (abs / 1000).toFixed(1) + 'k';
    return (abs / 1_000_000).toFixed(1) + 'M';
  });

  return (
    <>
      <div class="card">
        <button onClick={() => count(count() + 1)}>
          {count()} + 1
        </button>
        <button onClick={() => { count.value -= 1; }}>
          {count.value} - 1
        </button>
        <button onClick={() => { count.update((c: number) => 10 * c); }}>
          {count.value} * 10
        </button>
        <button onClick={() => { count.value /= 10; }}>
          {count.value} / 10
        </button>
        <p>
          Is count odd? {odd()}; {wordCount()}; {numberStr()}
        </p>
      </div>
    </>
  );
}

Store Ref (useStoreRef)

useStoreRef is the store counterpart of useSignalRef. It wraps Solid’s createStore and exposes a ref-like API.

Basic usage

import { useStoreRef } from '@frostime/solid-signal-ref';

const state = useStoreRef({
  count: 0,
  items: [] as string[],
});

Reading the store

state();         // returns the Store<T>
state.value;     // same as above (Vue style)
state.store;     // raw Store<T>

// Example:
state().count;
state.store.items.length;

Since Store<T> is a proxy, reading properties is reactive:

<p>Count: {state().count}</p>
<p>Items: {state.store.items.length}</p>

Updating the store

IStoreRef proxies setStore so you can use familiar patterns:

// Set a field
state('count', 1);

// Update a field based on previous value
state('count', c => c + 1);

// Shallow merge
state({ count: 2 });

// Updater function returning a partial object
state(prev => ({
  count: prev.count + 1,
}));

You can also use the underlying update (which is SetStoreFunction<T>):

state.update('items', items => [...items, 'new item']);

Derived values from store

derived creates a memoized accessor from the current store:

const state = useStoreRef({ count: 0, items: [] as string[] });

const summary = state.derived(s => `Count: ${s.count}, Items: ${s.items.length}`);

<p>{summary()}</p>

Unwrapped store

unwrap returns a non-proxy snapshot of the store:

const plain = state.unwrap();
// plain is a normal object, not a Solid store proxy

Store example

import { useStoreRef } from '@frostime/solid-signal-ref';

function TodoApp() {
  const todos = useStoreRef({
    list: [] as { id: number; title: string; done: boolean }[],
    nextId: 1,
  });

  const doneCount = todos.derived(s => s.list.filter(t => t.done).length);

  const addTodo = (title: string) => {
    todos.update('list', list => [
      ...list,
      { id: todos().nextId, title, done: false },
    ]);
    todos('nextId', id => id + 1);
  };

  const toggle = (id: number) => {
    todos.update('list', list =>
      list.map(t => (t.id === id ? { ...t, done: !t.done } : t)),
    );
  };

  return (
    <div>
      <p>Done: {doneCount()}</p>
      <ul>
        {todos().list.map(todo => (
          <li>
            <label>
              <input
                type="checkbox"
                checked={todo.done}
                onInput={() => toggle(todo.id)}
              />
              {todo.title}
            </label>
          </li>
        ))}
      </ul>
    </div>
  );
}