@scotttrinh/rescript-jotai

1.0.0 • Public • Published

rescript-jotai

ReScript bindings for Jotai. Primitive and flexible state management for React.

Installation

Install with npm:

npm install jotai @fattafatta/rescript-jotai

Or install with yarn:

yarn add jotai @fattafatta/rescript-jotai

Add @fattafatta/rescript-jotai as a dependency to your bsconfig.json:

"bs-dependencies": ["@rescript/react", "@fattafatta/rescript-jotai"]

Usage

Provider

A Provider works just like React context provider. If you don't use a Provider, it works as provider-less mode with a default store. A Provider will be necessary if we need to hold different atom values for different component trees.

module App = {
  @react.component
  let make = () =>
    <Jotai.Provider>
      ...
    </Jotai.Provider>
}

Create atoms

Atom type

Atoms have a value, a setter function (from Atom.Actions), and a set of tags that restrict which operations are allowed on the atom (e.g is the atom #resettable). Normally the type will be inferred automatically. If annotation is required it should be sufficient to provide the first type (the value).

Example:

let atom: Jotai.Atom.t<int, _, _> = Jotai.Atom.make(1)

Primitive atom (Jotai.Atom.make)

Create a (primitive) readable and writable atom.

let atom1 = Jotai.Atom.make(1)
let atom2 = Jotai.Atom.make('text')

Computed atom (Jotai.Atom.makeComputed)

Create a computed readonly atom. A computed atom can combine any number of readable atoms to create a single derived value. The syntax varies slightly from Jotai. Note the curly braces in ({get}).

let atom1 = Jotai.Atom.make(1)
let atom2 = Jotai.Atom.makeComputed(({get}) => get(atom1) + 1)
let atom3 = Jotai.Atom.makeComputed(({get}) => get(atom1) + get(atom2) + 1)

Computed async atom (Jotai.Atom.makeComputedAsync)

(Requires React.Suspense) Create an computed readonly atom with an async getter. All components will be notified when the returned promise resolves.

let atom1 = Jotai.Atom.make(1)
let atom2 = Jotai.Atom.makeComputedAsync(({get}) => {
  Js.Promise.make((~resolve, ~reject as _) => {
    let count = atom1->get + 1
    Js.Global.setTimeout(() => resolve(. count), 100)->ignore
  })
})

Computed writable atom (Jotai.Atom.makeWritableComputed)

Create a computed atom that supports read and write.

let atom1 = Jotai.Atom.make(1)
let atom2 = Jotai.Atom.makeWritableComputed(
  ({get}) => get(atom1) + 1,
  ({get, set}, arg) => {
    atom1->set(get(atom1) + arg)
  },
)

Computed writable async atom (Jotai.Atom.makeWritableComputedAsync)

Create a computed atom with asynchronous write. Jotai supports async write operations for computed atoms. Simply call 'set' when the promise resolves.

let atom1 = Jotai.Atom.make(1)
let atom2 = Jotai.Atom.makeWritableComputedAsync(
  ({get}) => get(atom1) + 1,
  ({get, set}, arg) => {
    Js.Promise.make((~resolve, ~reject as _) => {
      let count = get(atom1) + arg
      Js.Global.setTimeout(() => resolve(. count), 100)->ignore
    })->Js.Promise.then_(value => {
      atom1->set(value)
      Js.Promise.resolve()
    }, _)
  },
)

Computed writeonly atom (Jotai.Atom.makeWriteOnlyComputed)

Create a writeOnly computed atom.(Note: Sometimes the type can not be inferred and has to be annotated)

let atom1 = make(1)
let atom2: Jotai.Atom.t<int, _, _> = Jotai.Atom.makeWriteOnlyComputed(({get, set}, args) =>
  atom1->set(get(atom1) + args)
)

OnMount (Jotai.Atom.onMount)

The onMount function will be invoked when the atom is first used in a provider, and onUnmount will be invoked when it's not used.

let atom1 = Jotai.Atom.make(1)
atom1->Jotai.Atom.onMount(setAtom => {
  setAtom(a => a + 1) // increment count on mount
  () => () // return onUnmount function
})

Standard hook

Using read/write atoms (Jotai.Atom.use)

Standard hook to use with read/write atoms. (For handling of readOnly/writeOnly atoms see Jotai.Utils)

let atom1 = Jotai.Atom.make(1)
let (value, setValue) = Jotai.Atom.use(atom1)

Utils

Atom with localStorage (Jotai.Utils.AtomWithStorage.make)

Creates an atom with a value persisted in localStorage Currently only localStorage is supported.

let atom1 = Jotai.Utils.AtomWithStorage.make('storageKey', 1)

Resettable atom (Jotai.Utils.AtomWithReset.make)

Creates an atom that can be resetted to its initialValue with the useResetAtom hook.

let atom = Jotai.Utils.AtomWithReset.make(1)
// ... change value ...
let reset = Jotai.Utils.useResetAtom(atom)
reset()

Atom with default (Jotai.Utils.AtomWithDefault.make)

Create a resettable primitive atom. Its default value can be specified with a read function instead of a static initial value.

let atom1 = Jotai.Atom.make(1)
let atom2 = Jotai.Utils.AtomWithDefault.make(({get}) => atom1->get + 1)

Atom with Reducer (Jotai.Utils.AtomWithReducer.make)

Creates an atom that uses a reducer to update its value.

type actionType = Inc(int) | Dec(int)
let countReducer = (prev, action) => {
  switch action {
  | Inc(num) => prev + num
  | Dec(num) => prev - num
  }
}
let atom = Utils.AtomWithReducer.make(0, countReducer)
let (value, dispatch) = Atom.use(atom)
Inc(1)->dispatch

Utils Hooks

Get only the update function (Jotai.Utils.useUpdateAtom)

A hook that returns only the update function of an atom. Can be used to access writeOnly atoms.

let atom = Jotai.Atom.make(1)
let setValue = Jotai.Utils.useUpdateAtom(atom)
setValue(prev => prev + 1)

Get only the value (Jotai.Utils.useAtomValue)

A hook that returns only the value of an atom. Can be used to access readOnly atoms.

let atom = Jotai.Atom.make(1)
let value = Jotai.Utils.useAtomValue(atom)

Reset an atom (Jotai.Utils.useResetAtom)

Returns a function that can be used to reset a resettable atom.

let atom = Jotai.Utils.AtomWithReset(1)  // value: 1
let (_, setValue) = Jotai.Atom.use(atom)
setValue(2)  // value: 2
let resetValue = Jotai.Utils.useResetAtom(atom)
resetValue()  // value back to: 1

Pass a reducer to a writable atom (Jotai.Utils.useReducerAtom)

Allows to use a reducer function with a primitive atom.

type actionType = Inc(int) | Dec(int)
let countReducer = (prev, action) => {
  switch action {
  | Inc(num) => prev + num
  | Dec(num) => prev - num
  }
}
let atom = Jotai.Atom.make(0)
let (value, dispatch) = Jotai.Utils.useReducerAtom(atom, countReducer)
Inc(1)->dispatch

Alternatives

This package was greatly inspired by re-jotai. I just preferred to have a different syntax for the get/set functions.

Missing functions from Jotai

These functions are not (yet) supported.

  • atomWithObservable
  • atomWithHash
  • atomFamily
  • selectAtom
  • useAtomCallback
  • freezeAtom
  • splitAtom
  • waitForAll
  • useHydrateAtoms

Package Sidebar

Install

npm i @scotttrinh/rescript-jotai

Weekly Downloads

0

Version

1.0.0

License

MIT

Unpacked Size

29.7 kB

Total Files

19

Last publish

Collaborators

  • scotttrinh