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

@lfades/atom

v1.0.1

Published

Straightforward state management library for React.

Readme

@lfades/atom

Straightforward state management library for React. You can learn more about it at atom.lfades.com.

Installation

Install the package with your package manager of choice:

pnpm add @lfades/atom
npm install @lfades/atom
yarn add @lfades/atom

Now you can create an atom and subscribe to it:

import { atom, useAtom } from '@lfades/atom';

const counterAtom = atom(0);

const Counter = () => {
  const [count, setCount] = useAtom(counterAtom);

  return (
    <div>
      <h1>Counter: {count}</h1>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <button onClick={() => setCount(count - 1)}>Decrement</button>
    </div>
  );
};

export default Counter;

That's it! It only takes a few minutes to understand what the library does so I encourage you to read the source code.

API

atom

function atom<Value>(initialValue: Value): Atom<Value>;

Creates an atom with the given initialValue.

import { atom } from '@lfades/atom';

const counterAtom = atom(0);

You can read the value of the atom without subscribing to it by using the get method:

atom.get(); // 0

Similarly, you can update the value of the atom with set:

atom.set(1);
atom.get(); // 1

When you update the value of the atom, all components subscribed to it will re-render.

useAtom

function useAtom<Value>(atom: Atom<Value>): [Value, (value: Value) => void];

Returns the current value of the atom and a setter function to update it. This also subscribes the component to the atom, so it will re-render when the atom value changes.

The setter returned by useAtom is equivalent to atom.set. So the following are equivalent:

import { useAtom } from '@lfades/atom';

const [count, setCount] = useAtom(counterAtom);
// ..
setCount(1);
setCount === counterAtom.set; // true
const count = useAtom(counterAtom)[0];
// ..
counterAtom.set(1);

Creating an atom inside a component

This is a valid use case, but be sure to add useMemo to prevent the atom from being recreated on every render:

const counterAtom = useMemo(() => atom(0), []);
const [count, setCount] = useAtom(counterAtom);

An atom created this way will work similarly to useState. However, you can pass down the atom through props and allow other components to subscribe to it if needed. This can prove particularly useful when combined with React Context.

Atoms also have a unique identifier in atom.id that you can use as the key attribute.

useSubscribe

function useSubscribe<Value>(
  atom: Atom<Value>,
  cb: SubFn<Value>,
  deps?: DependencyList
): void;

Subscribes to the atom and calls the callback function with the new value whenever it changes.

import { useSubscribe } from '@lfades/atom';

useSubscribe(counterAtom, (value) => {
  console.log(value);
});

If the callback function has dependencies, you can pass them as the third argument:

useSubscribe(
  counterAtom,
  (value) => {
    console.log(value, dep);
  },
  [dep]
);

useHydrate

function useHydrate(cb: () => void, deps: DependencyList): void;

Allows you to hydrate atoms, useful for updating atoms with data from the server. For example, we can have atoms be created and shared by a context provider, and hydrate them with server data:

// atoms-context.tsx
import { atom, useHydrate } from '@lfades/atom';

const atoms = { counterAtom: atom(0) };
export const atomsContext = React.createContext(atoms);

export function AtomsProvider({ children, data }) {
  useHydrate(() => {
    if (data) {
      atoms.counterAtom.set(data.counter);
    }
  }, [data]);

  return (
    <atomsContext.Provider value={atoms}>{children}</atomsContext.Provider>
  );
}
// page.tsx
import { AtomsProvider } from './atoms-context';
import { Counter } from './counter';

async function Page() {
  const data = await fetchData();
  return (
    <Atoms data={data}>
      <Counter />
    </Atoms>
  );
}

The Counter component can then get the atom from the context and subscribe to the atom:

// counter.tsx
import { useAtom } from '@lfades/atom';
import { atomsContext } from './atoms-context';

function Counter() {
  const { counterAtom } = React.useContext(atomsContext);
  const [count, setCount] = useAtom(counterAtom);

  return (
    <div>
      <h1>Counter: {count}</h1>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <button onClick={() => setCount(count - 1)}>Decrement</button>
    </div>
  );
}
const counterAtom = atom(0);

Contributing

After cloning the repository, install dependencies with pnpm:

pnpm install

Run the main website:

pnpm dev

And then open the site at http:localhost:3000 and test your changes in the counter demo.

Testing the library with a different app

Alternatively, you can link the package and use it with an app outside the monorepo. First navigate to the package directory:

cd packages/atom

and then create a link for the package:

pnpm link --global

You can install the package in an app with:

pnpm link @lfades/atom

To remove the linked package run the following command:

pnpm uninstall --global @lfades/atom

Releasing a new version

After you're done with your changes, run:

pnpm changeset

And add a good description of your changes.