jotai-wrapper, a wrapper library around jotai
Tags: react, jotai
Published: 2024-02-26 20:46:45

I've just published [jotai-wrapper](https://www.npmjs.com/package/jotai-wrapper), a super tiny and simple utility library that makes using [jotai](https://jotai.org/) even simpler. It comes from the necessity to migrate a project with [react-context-slices](https://react-context-slices.github.io/) to jotai. Both libraries share a similar API. While in react-context-slices you have the `useSlice` hook, in jotai you have the `useAtom`, `useSetAtom`, and `useAtomValue` hooks. In react-context-slices you define either React Context or Redux slices, while in jotai you define atoms. The need for the migration from the first to the second was a high memory usage by react-context-slices when using React Context slices.

## The API

jotai-wrapper default exports a function, `getAPIFromAtoms`. To use it you must define an `atoms.js` file in your project, like this:

```javascript
// atoms.js
import { atom } from "jotai";
import getAPIFromAtoms from "jotai-wrapper";

export const { useAtom, useSetAtom, useAtomValue, getAtom, selectAtom } =
  getAPIFromAtoms({
    counter: atom(0),
    todos: atom([]),
    messagesLastFoundId: atom(-1),
    invitationsLastFoundId: atom(-1),
    // rest of atoms
  });
```

As you can see this function, `getAPIFromAtoms`, gives us three hooks and two functions.

## `useAtom`, `useSetAtom`, and `useAtomValue`

These three hooks behave the same as in jotai, but you pass to them a string instead of an atom (you can still pass them an atom if you wish). For example:

```javascript
// counter.js
import {useAtom} from "./atoms";

export default function Counter(){
    const [counter,setCounter]=useAtom("counter");

    return <>
    <button onClick={()=>setCounter(c=>c+1)}>+</button>{counter}
    <>;
}
```

The fact to use strings instead of atoms in the this three hooks allows for dynamic referencing, like this:

```javascript
// use-last-found-id.js
import { useSetAtom } from "./atoms";

export function useLastFountId({ prefix }) {
  const setLastFoundId = useSetAtom(`${prefix}LastFoundId`);
  // ...
}
```

## `getAtom` and `selectAtom`

These are the other two functions returned by the call to `getAPIFromAtoms` in `atoms.js` file. 

`getAtom` simply returns the atom wich the string we pass refers to. For example: `const counterAtom = getAtom("counter");`.

`selectAtom` is more useful. We use it like this:

```javascript
// todos.js
import { selectAtom, useAtomValue } from "./atoms";
import { useMemo } from "react";

export default function Todos({ index, id }) {
  const todoAtIndex = useAtomValue(
    useMemo(() => selectAtom("todos", (todos) => todos[index]), [index])
  );
  const todoWithId = useAtomValue(
    useMemo(
      () =>
        selectAtom("todos", (todos) => todos.find((todo) => todo.id === id)),
      [id]
    )
  );
  //...
}
```

It's important to note that this `selectAtom` function returned by the call to `getAPIFromAtoms` in `atoms.js` file is different than the `selectAtom` from jotai. To use the `selectAtom` from jotai you must import it like this: `import {selectAtom} from "jotai/utils";`.

## Summary

So this is it. You can use jotai with jotai-wrapper in a simpler way. Thanks for reading.