Skip to content

Commit

Permalink
Merge branch 'main' into feature/observable-initial-data
Browse files Browse the repository at this point in the history
  • Loading branch information
dai-shi committed Apr 4, 2022
2 parents e8f976b + 59912a3 commit 2686800
Show file tree
Hide file tree
Showing 33 changed files with 298 additions and 237 deletions.
2 changes: 1 addition & 1 deletion .github/FUNDING.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ community_bridge: # Replace with a single Community Bridge project-name e.g., cl
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
custom: ['https://daishi.gumroad.com/l/learn-jotai'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
32 changes: 16 additions & 16 deletions docs/advanced-recipes/atom-creators.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ nav: 5.02

> `atomWithToggle` creates a new atom with a boolean as initial state & a setter function to toggle it.
This avoids the boilerplate of having to setup another atom just to update the state of the first.
This avoids the boilerplate of having to set up another atom just to update the state of the first.

```ts
import { WritableAtom, atom } from 'jotai'
Expand All @@ -24,9 +24,9 @@ export function atomWithToggle(
}
```

An optional initial state can be provided as first argument.
An optional initial state can be provided as the first argument.

The setter function can have an optional arg to force a particular state (if you want to make a setActive function out of it for example).
The setter function can have an optional argument to force a particular state, such as if you want to make a setActive function out of it.

Here is how it's used.

Expand All @@ -37,7 +37,7 @@ import { atomWithToggle } from 'XXX'
const isActiveAtom = atomWithToggle(true)
```

And in a component :
And in a component:

```tsx
const Toggle = () => {
Expand All @@ -57,9 +57,9 @@ const Toggle = () => {

## atomWithToggleAndStorage

> `atomWithToggleAndStorage` does the same as [`atomWithToggle`](#atom-with-toggle) but also persist the state anytime it changes in given storage using [`atomWithStorage`](../api/utils.mdx#atom-with-storage).
> `atomWithToggleAndStorage` is like [`atomWithToggle`](#atom-with-toggle) but also persist the state anytime it changes in given storage using [`atomWithStorage`](../api/utils.mdx#atom-with-storage).
Here is the source :
Here is the source:

```ts
import { WritableAtom, atom } from 'jotai'
Expand All @@ -83,20 +83,20 @@ export function atomWithToggleAndStorage(
}
```

And how it's used :
And how it's used:

```ts
import { atomWithToggleAndStorage } from 'XXX'

// will have an initial value set to false & be stored in localStorage under the key "isActive"
// will have an initial value set to false & get stored in localStorage under the key "isActive"
const isActiveAtom = atomWithToggleAndStorage('isActive')
```

The usage in a component is also the same as [`atomWithToggle`](#atom-with-toggle).

## atomWithCompare

> `atomWithCompare` creates atom that only triggers updates when custom compare function `areEqual(prev, next)` is false.
> `atomWithCompare` creates atom that triggers updates when custom compare function `areEqual(prev, next)` is false.
This can help you avoid unwanted re-renders by ignoring state changes that don't matter to your application.

Expand All @@ -119,7 +119,7 @@ export function atomWithCompare<Value>(
}
```

Here's how you'd use it to implement an atom that ignores updates that are shallow-equal:
Here's how you'd use it to make an atom that ignores updates that are shallow-equal:

```ts
import { atomWithCompare } from 'XXX'
Expand Down Expand Up @@ -182,7 +182,7 @@ export function atomWithRefresh<T>(fn: (get: Getter) => T) {
}
```

Here's how you'd use it to implement an refreshable source of data:
Here's how you'd use it to implement an refresh-able source of data:

```ts
import { atomWithRefresh } from 'XXX'
Expand Down Expand Up @@ -219,7 +219,7 @@ const PostsList = () => {

> `atomWithListeners` creates an atom and a hook. The hook can be called to
> add a new listener. The hook takes as an argument a callback, and that
> callback will be called every time the atom's value is set. The hook also
> callback is called every time the atom's value is set. The hook also
> returns a function to remove the listener.
This can be useful when you want to create a component that can listen to when
Expand All @@ -235,7 +235,7 @@ type Callback<Value> = (
get: Getter,
set: Setter,
newVal: Value,
prevVal: Value,
prevVal: Value
) => void

export function atomWithListeners<Value>(initialValue: Value) {
Expand All @@ -250,7 +250,7 @@ export function atomWithListeners<Value>(initialValue: Value) {
get(listenersAtom).forEach((callback) => {
callback(get, set, newVal, prevVal)
})
},
}
)
const useListener = (callback: Callback<Value>) => {
const setListeners = useUpdateAtom(listenersAtom)
Expand Down Expand Up @@ -284,8 +284,8 @@ function EvenCounter() {
setEvenCount((c) => c + 1)
}
},
[setEvenCount],
),
[setEvenCount]
)
)

return <>Count was set to an even number {evenCount} times.</>
Expand Down
4 changes: 4 additions & 0 deletions docs/advanced-recipes/custom-useatom-hooks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,8 @@ useFocusAtom(anAtom) {
}
```

### CodeSandbox

<CodeSandbox id="y5wef8" />

Please note that in this case `keyFn` must be stable, either define outside render or warp with `useCallback`.
20 changes: 10 additions & 10 deletions docs/advanced-recipes/large-objects.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ title: Large objects
nav: 5.01
---

> All of the examples and descriptions below are based on this [codesandbox](https://codesandbox.io/s/zealous-sun-f2qnl?file=/src/App.tsx), so it will give you a better understanding if you check it out along these examples.
> The examples and descriptions below are based on this [codesandbox](https://codesandbox.io/s/zealous-sun-f2qnl?file=/src/App.tsx), so it will give you a better understanding if you check it out along with these examples.
Sometimes we have big data we need to keep into atoms, we may need to change that data in some levels, or we need to use part of that data, but we can't listen to all these changes or use all that data for just a specific part.
Sometimes we have nested data we need to store in atoms, and we may need to change that data at different levels, or we need to use part of that data without listening to all changes.

Consider this example:

Expand Down Expand Up @@ -43,7 +43,7 @@ const initialData = {

> `focusAtom` creates a new atom, based on the focus that you pass to it. [jotai/optics](../integrations/optics.mdx#focus-atom)
We use this utility to focus an atom and create an atom of a specific part of the data. For example we may need to consume the people property of the above data, Here's how we do it.
We use this utility to focus an atom and create an atom from a specific part of the data. For example we may need to consume the people property of the above data, Here's how we do it:

```jsx
import { atom } from 'jotai'
Expand All @@ -56,21 +56,21 @@ const peopleAtom = focusAtom(dataAtom, (optic) => optic.prop('people'))

`focusAtom` returns `WritableAtom` which means it's possible to change the `peopleAtom` data.

If we change the `film` property of the above data example, the `peopleAtom` won't cause us a re-render, so that's one of the points of using `focusAtom`.
If we change the `film` property of the above data example, the `peopleAtom` won't cause a re-render, so that's one of the benefits of using `focusAtom`.

## splitAtom

> The `splitAtom` utility is useful, when you want to get an atom for each element in a list. [jotai/utils](../api/utils.mdx#split-atom)
> The `splitAtom` utility is useful when you want to get an atom for each element in a list. [jotai/utils](../api/utils.mdx#split-atom)
We use this utility for atoms that return arrays as their values, for example the `peopleAtom` we made above returns the people property array, so we can return an atom for each item of that array. If the array atom is writable, `splitAtom` returned atoms are going to be writable, if the array atom is read-only, items atoms are going to be read-only too.
We use this utility for atoms that return arrays as their values. For example, the `peopleAtom` we made above returns the people property array, so we can return an atom for each item of that array. If the array atom is writable, `splitAtom` returned atoms are going to be writable, if the array atom is read-only, the returned atoms will be read-only too.

```jsx
import { splitAtom } from 'jotai/utils'

const peopleAtomsAtom = splitAtom(peopleAtom)
```

And that's how we use it in components.
And this is how we use it in components.

```jsx
const People = () => {
Expand All @@ -89,16 +89,16 @@ const People = () => {

> This function creates a derived atom whose value is a function of the original atom's value. [jotai/utils](../api/utils.mdx#select-atom)
This utility is similar to `focusAtom`, but we use it when we have a read-only atom to select part of it, and it always returns a read-only atom.
This utility is like `focusAtom`, but we use it when we have a read-only atom to select part of it, and it always returns a read-only atom.

Assume we want to consume the info data, and its data is always unchangeable, so we can make a read-only atom from it and select that created atom.
Assume we want to consume the info data, and its data is always unchangeable. We can make a read-only atom from it and select that created atom.

```jsx
// first we create a read-only atom based on initialData.info
const readOnlyInfoAtom = atom((get) => get(dataAtom).info)
```

Then we are going to consume it in our component:
Then we use it in our component:

```jsx
import { atom, useAtom } from 'jotai'
Expand Down
17 changes: 8 additions & 9 deletions docs/api/babel.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,37 @@ nav: 2.04

Jotai is based on object references and not keys (like Recoil). This means there's no identifier for atoms. To identify atoms, it's possible to add a `debugLabel` to an atom, which can be found in React devtools.

However, this can quickly become cumbersome to add a `debugLabel` to every atom.
However, this can quickly become cumbersome to add a `debugLabel` to every atom.

This `babel` plugin adds a `debugLabel` to every atom, based on its identifer.

The plugin transforms this code:

```ts
export const countAtom = atom(0);
export const countAtom = atom(0)
```

Into:

```ts
export const countAtom = atom(0);
countAtom.debugLabel = "countAtom";
export const countAtom = atom(0)
countAtom.debugLabel = 'countAtom'
```

Default exports are also handled, based on the file naming:

```ts
// countAtom.ts
export default atom(0);
export default atom(0)
```

Which transform into:

```ts
// countAtom.ts
const countAtom = atom(0);
countAtom.debugLabel = "countAtom";
export default countAtom;
const countAtom = atom(0)
countAtom.debugLabel = 'countAtom'
export default countAtom
```

## Usage
Expand Down Expand Up @@ -92,4 +92,3 @@ With a `babel` configuration file:
### Parcel

<CodeSandbox id="bgf3b" />

Loading

0 comments on commit 2686800

Please sign in to comment.