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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@respite/atom

v4.0.2

Published

> TODO: description

Downloads

98

Readme

@respite/atom

An atom-based state library.

This will just cover getting started and the api, for an overarching explanation of respite, see the repo readme

Getting started

npm install @respite/core @respite/query @respite/atom

Usage

import React from "react";
import { Provider, useAtom, atom, molecule } from "@respite/atom";

const USER_ID = atom({ default: 1 });

const USER = molecule({
  get({ get }) {
    const id = get(USER_ID);
    return () => fetch(`/api/user/${id}`);
  },
  set({ get }) {
    const id = get(USER_ID);
    return (values) => patch(`/api/user/${id}`, values);
  },
});

function MyComponent() {
  const [user, setUser] = useAtom(USER);

  return <div>{user.name}</div>;
}

function App() {
  return (
    <Provider>
      <Suspense fallback={<div>loading</div>}>
        <MyComponent />
      </Suspense>
    </Provider>
  );
}

atom

<T>({ default?: T }): Atom<T>

This is the smallest "unit of state". You define the atom globally and then that state is available in any component by passing it into useState or useValue.

  • default The default value of the atom. If not provided it defaults to undefined.

molecule

<T, D extends any[]>({
  get(callback: (fn: () => T | Promise<T>, deps?: any[]), args: D): T | Promise<T> | () => T | Promise<T>,
  get({ get: <U>(atom: Atom<U>, deps?: any[]) => U }, args: D): T | Promise<T> | () => T | Promise<T>,
  set(callback: (fn: () => T | Promise<T>, deps?: any[]), args: D): (value: T) => any,
  set({ get: <U>(atom: Atom<U>, deps?: any[]) => U, set: <U>(atom: Atom<U>, deps?: any[]) => (value: U) => void }, args: D): (value: T) => any,
}): Molecule<T, D>;

Okay this signature looks pretty complex so lets break it down by example.

A molecule can have a getter and/or a setter.

get

Here's a very basic getter:

const m = molecule({
  get() {
    return "foo";
  },
});

calling useState(m) will return 'foo'

If you want to access other atoms/molecules you can do so using the get helper:

const m = molecule({
  get({ get }) {
    const foo = get(FOO_ATOM);
    return foo;
  },
});

The getter is called at "react level" which means you can safely call any other react hooks. However, in order for the molecule to understand when it needs to recalculate, you need to subscribe your dependencies (just like if you were calling useEffect or useMemo):

const m = molecule({
  get(memo) {
    const [foo] = useState(FOO_ATOM);
    const thing = useThing();

    return memo(() => {
      return foo + thing;
    }, [foo, thing]);
  },
});

So now when the getter is called, we're telling react that whenever foo or thing changes, the molecule must also be recomputed.

Hopefully these 3 types of getter make sense. You've essentially got basic getters, atom-based getters and hook-based getters

set

Set is very similar to get:

const m = molecule({
  set() {
    return (value) => {
      // save the value
    };
  },
});
const m = molecule({
  set({ set }) {
    const setFoo = set(FOO_ATOM);

    return (value) => {
      setFoo(value);
    };
  },
});
const m = molecule({
  set(memo) {
    const [foo, setFoo] = useState(FOO_ATOM);
    const thing = useThing();

    return memo(
      (value) => {
        setFoo(value + thing);
      },
      [foo, thing]
    );
  },
});

it's also worth noting that both the getter and setter functions can return promises

args

The final piece of the molecule puzzle is args. A molecule can optionally rely on external dependencies passed in from the component level. This is similar to recoil's atomFamily concept:

const m = molecule<string, [number]>({
  get({ get }, [index]) {
    const list = get(LIST_ATOM);
    return list[index];
  },
});

You would then call it with

useState(m, [1]);

It's important to note that a specific set of args will result in a specific instance of the molecule. For example:

const [first] = useState(m, [1]);
const [second] = useState(m, [2]);

useState / useAtom

<T>(atom: Atom<T>, deps?: any[]): [ T, (value: T) => void ]
<T>(molecule: Molecule<T>, deps?: any[]): [ T, (value: T) => void ]

useValue

<T>(atom: Atom<T>, deps?: any[]): T

useReset

(atom: Atom): () => void

Returns a reset function that reverts the atom to its initial state

useInitialize

<T>(atom: Atom<T>, value: T): T

this hook lets you set an initial value for an atom, allowing you override the atom's own default value the most obvious use case for this is when testing and you want the atom to be in a specific state

Provider

ComponentType<{
  cacheTime?: number,
}>

The provider component is required to handle the caching of state between components, you should place it near the top of your application.

const App = () => (
  <Provider>
    <Page />
  </Provider>
);