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 🙏

© 2025 – Pkg Stats / Ryan Hefner

bonezjs

v0.1.3

Published

The backbone of React state

Downloads

12

Readme


What is Bonez?

Bonez is a state library for React that takes the state out from React for easier state management.

Each unit of state is called bone, and all the bones build the entire state skeleton of the application.

A unit of state can be as simple as a boolean, number or a string, but it can also be a complex data structure such as an array, object or a function.

How Bonez differs from useState?

While useState is a React hook, a bone is a simple JS object with some methods and internal values.

A bone exposes 4 methods:

  1. getValue - this method returns the current bone value.
  2. setValue - this method sets a new value of the bone. If the value is the same as the current value (same value for boolean, number, string, same reference for array, object or function), by default, nothing changes. This can be controlled by passing compare function to decide when a value is the same as the previous value.
  3. watch - this adds a watcher for the bone value, every time the bone value is changed via the setValue method, all watchers are triggered with the new value. For easy unwatch, every call to watch returns an unwatch value to remove the specific watcher that was just added. To keep things performant and clean, watchers callbacks are indexed by their function reference, so adding the same function again as a watcher will actually not add another watcher.
  4. unwatch - this removes the provided watcher callback from the watchers list. Does nothing if the provided watcher function does not exist on the list.

So how it works with React?

By the use of hooks.

When you pass a bone to useBone / useBoneValue / useDerivedBoneValue - you are making the bone and your React component "connected". Every change to that bone will trigger a render for all the components that have one of those hooks.

The useBoneSet hook WILL NOT trigger a re-render of the component alone, unless the component also has one of the other useBone* hooks. This is good for performance, since if your component only need to trigger a change to a value, but it is not dependent on it, it will not rerender.

Note: Under the hood, all useBone* hooks (except for useBoneSet) are based on useState to trigger component renders.

Installation

Add bonezjs using your favorite package manager. Foe example, using npm:

npm install bonezjs

Examples

Simple example

import { bone, useBoneValue, useBoneSet } from 'bonez'

const counter = bone(0)

const CounterDigits = () => {
  const count = useBoneValue(counter)
  
  return (
    <div>
      <h1>{count}</h1>
    </div>
  )
}

const CounterControls = () => {
  const setCount = useBoneSet(counter)
  
  return (
    <div>
      <button onClick={() => setCount((count) => count + 1)}>Count</button>
    </div>
  )
  
}

const Counter = () => {
  return (
    <>
      // This will render everytime counter bone value changes
      <CounterDigits />

      // This will render only once, since it does not depends on counter bone value
      <CounterControls /> 
    </>
  )
}

Pass a custom compare function

import { bone, useBoneValue, useBoneSet } from 'bonez'

interface User {
  email: string,
  firstName: string,
  lastName: string
}

const userA : User = {
  email: '[email protected]',
  firstName: 'A',
  lastName: 'A'
}

const userB : User = {
  email: '[email protected]',
  firstName: 'B',
  lastName: 'B'
}

const user = bone<User|null>(null, {
  compare: (value, newValue) => value?.email === value?.email
})

const UserProfile = () => {
  const userProfile = useBoneValue(user)
  
  if (!userProfile) return null
  
  return (
    <div>
      <h1>{userProfile.email}</h1>
      <h2>{userProfile.firstName} {userProfile.lastName}</h2>
    </div>
  )
}

const Login = () => {
  const setUser = useBoneSet(user)
  
  return (
    <div>
      <button onClick={() => setUser({ ...userA })}>Login user A</button>
      <button onClick={() => setUser({ ...userB })}>Login user B</button>
    </div>
  )
  
}

const UserApp = () => {
  return (
    <>
      // This will render everytime user bone value changes, but since we compare by email,
      // if we set the same user again, even though we create a new object reference every time, 
      // it will not be rendered
      <UserProfile />

      // This will render only once, since it does not depends on user bone value
      <Login /> 
    </>
  )
}

This is useful to prevent redundant renders if nothing actually changes, a simple example will be to compare objects that are returning from the server, and have id and updatedAt fields for example - if the same id was set, and the updatedAt value is not different, than the object was not actually changed and there is no need to render the component again.