Skip to content

Commit

Permalink
feat(website): reorganize docs (#1733)
Browse files Browse the repository at this point in the history
* feat(website): reorganize docs

* fix: remove Prettier directive

* fix(website): restore prop

* feat(website): reorder introduction

* feat(website): revise table of contents

* chore(docs): run Prettier
  • Loading branch information
sandren authored Feb 2, 2023
1 parent 202b140 commit 932d82e
Show file tree
Hide file tree
Showing 72 changed files with 1,179 additions and 1,059 deletions.
420 changes: 0 additions & 420 deletions docs/api/core.mdx

This file was deleted.

85 changes: 0 additions & 85 deletions docs/api/utils.mdx

This file was deleted.

6 changes: 1 addition & 5 deletions docs/basics/comparison.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Comparison
nav: 1.04
nav: 6.02
---

Jotai was born to solve extra re-render issues in React.
Expand Down Expand Up @@ -96,8 +96,6 @@ const Component2 = () => {
}
```

---

## How is Jotai different from Zustand?

### Name
Expand Down Expand Up @@ -134,8 +132,6 @@ The major difference is the state model. Zustand is a single store (although you
- If you prefer Redux devtools, Zustand is good to go.
- If you want to make use of Suspense, Jotai is the one.

---

## How is Jotai different from Recoil?

(Disclaimer: the author is not very familiar with Recoil, this may be biased and inaccurate.)
Expand Down
2 changes: 1 addition & 1 deletion docs/basics/concepts.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Concepts
nav: 1.01
nav: 6.01
---

Jotai is a library that will make you return to the basics of React development & keep everything simple.
Expand Down
2 changes: 1 addition & 1 deletion docs/basics/showcase.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Showcase
nav: 1.05
nav: 6.03
---

- Text Length example [![Open in CodeSandbox](https://img.shields.io/badge/Open%20in-CodeSandbox-blue?style=flat-square&logo=codesandbox)](https://githubbox.com/pmndrs/jotai/tree/main/examples/text_length)
Expand Down
145 changes: 145 additions & 0 deletions docs/core/atom.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
---
title: atom
description: This doc describes core `jotai` bundle.
nav: 2.01
keywords: atom,primitive,derived,debug,label,onmount
---

## atom

The `atom` function is to create an atom config.
We call it "atom config" as it's just a definition and it doesn't yet hold a value.
We may also call it just "atom" if the context is clear.

An atom config is an immutable object. The atom config object doesn't hold a value. The atom value exists in a store.

To create a primitive atom (config), all you need is to provide an initial value.

```js
import { atom } from 'jotai'

const priceAtom = atom(10)
const messageAtom = atom('hello')
const productAtom = atom({ id: 12, name: 'good stuff' })
```

You can also create derived atoms. We have three patterns:

- Read-only atom
- Write-only atom
- Read-Write atom

To create derived atoms, we pass a read function and an optional write function.

```js
const readOnlyAtom = atom((get) => get(priceAtom) * 2)
const writeOnlyAtom = atom(
null, // it's a convention to pass `null` for the first argument
(get, set, update) => {
// `update` is any single value we receive for updating this atom
set(priceAtom, get(priceAtom) - update.discount)
}
)
const readWriteAtom = atom(
(get) => get(priceAtom) * 2,
(get, set, newPrice) => {
set(priceAtom, newPrice / 2)
// you can set as many atoms as you want at the same time
}
)
```

`get` in the read function is to read the atom value.
It's reactive and read dependencies are tracked.

`get` in the write function is also to read atom value, but it's not tracked.
Furthermore, it can't read unresolved async values in Jotai v1 API.

`set` in the write function is to write atom value.
It will invoke the write function of the target atom.

**Note**: Atom configs can be created anywhere, but referential equality is important.
They can be created dynamically too.
To create an atom in render function, `useMemo` or `useRef` is required to get a stable reference. If in doubt about using `useMemo` or `useRef` for memoization, use `useMemo`.

```js
const Component = ({ value }) => {
const valueAtom = useMemo(() => atom({ value }), [value])
// ...
}
```

### Signatures

```ts
// primitive atom
function atom<Value>(initialValue: Value): PrimitiveAtom<Value>

// read-only atom
function atom<Value>(read: (get: Getter) => Value | Promise<Value>): Atom<Value>

// writable derived atom
function atom<Value, Update>(
read: (get: Getter) => Value | Promise<Value>,
write: (get: Getter, set: Setter, update: Update) => void | Promise<void>
): WritableAtom<Value, Update>

// write-only derived atom
function atom<Value, Update>(
read: Value,
write: (get: Getter, set: Setter, update: Update) => void | Promise<void>
): WritableAtom<Value, Update>
```

- `initialValue`: the initial value that the atom will return until its value is changed.
- `read`: a function that's called on every re-render. The signature of `read` is `(get) => Value | Promise<Value>`, and `get` is a function that takes an atom config and returns its value stored in Provider as described below. Dependency is tracked, so if `get` is used for an atom at least once, the `read` will be reevaluated whenever the atom value is changed.
- `write`: a function mostly used for mutating atom's values, for a better description; it gets called whenever we call the second value of the returned pair of `useAtom`, the `useAtom()[1]`. The default value of this function in the primitive atom will change the value of that atom. The signature of `write` is `(get, set, update) => void | Promise<void>`. `get` is similar to the one described above, but it doesn't track the dependency. `set` is a function that takes an atom config and a new value which then updates the atom value in Provider. `update` is an arbitrary value that we receive from the updating function returned by `useAtom` described below.
```js
const primitiveAtom = atom(initialValue)
const derivedAtomWithRead = atom(read)
const derivedAtomWithReadWrite = atom(read, write)
const derivedAtomWithWriteOnly = atom(null, write)
```

There are two kinds of atoms: a writable atom and a read-only atom. Primitive atoms are always writable. Derived atoms are writable if the `write` is specified. The `write` of primitive atoms is equivalent to the `setState` of `React.useState`.

### `debugLabel` property

The created atom config can have an optional property `debugLabel`. The debug label is used to display the atom in debugging. See [Debugging guide](../guides/debugging.mdx) for more information.

Note: While, the debug labels don’t have to be unique, it’s generally recommended to make them distinguishable.

### `onMount` property

The created atom config can have an optional property `onMount`. `onMount` is a function which takes a function `setAtom` and returns `onUnmount` function optionally.

The `onMount` function is called when the atom is first used in a provider, and `onUnmount` is called when it’s no longer used. In some edge cases, an atom can be unmounted and then mounted immediately.

```js
const anAtom = atom(1)
anAtom.onMount = (setAtom) => {
console.log('atom is mounted in provider')
setAtom(c => c + 1) // increment count on mount
return () => { ... } // return optional onUnmount function
}
```

Calling `setAtom` function will invoke the atom’s `write`. Customizing `write` allows changing the behavior.

```js
const countAtom = atom(1)
const derivedAtom = atom(
(get) => get(countAtom),
(get, set, action) => {
if (action.type === 'init') {
set(countAtom, 10)
} else if (action.type === 'inc') {
set(countAtom, (c) => c + 1)
}
}
)
derivedAtom.onMount = (setAtom) => {
setAtom({ type: 'init' })
}
```
74 changes: 74 additions & 0 deletions docs/core/provider.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
title: Provider
description: This doc describes core `jotai` bundle.
nav: 2.04
keywords: provider,usestore,ssr
---

## Provider

The `Provider` component is to provide state for a component sub tree.
Multiple Providers can be used for multiple subtrees, and they can even be nested.
This works just like React Context.

If an atom is used in a tree without a Provider,
it will use the default state. This is so-called provider-less mode.

Providers are useful for three reasons:

1. To provide a different state for each sub tree.
2. To accept initial values of atoms.
3. To clear all atoms by remounting.

```jsx
const SubTree = () => (
<Provider>
<Child />
</Provider>
)
```

### Signatures

```ts
const Provider: React.FC<{
store?: Store
}>
```
Atom configs don't hold values. Atom values reside in separate stores. A Provider is a component that contains a store and provides atom values under the component tree. A Provider works 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. Provider can take an optional prop `store`.
```jsx
const Root = () => (
<Provider>
<App />
</Provider>
)
```

### `store` prop

A Provider accepts an optional prop `store` that you can use for the Provider subtree.

#### Example

```jsx
const myStore = createStore()

const Root = () => (
<Provider store={myStore}>
<App />
</Provider>
)
```

## useStore

This hook returns a store within the component tree.

```jsx
const Component = () => {
const store = useStore()
// ...
}
```
38 changes: 38 additions & 0 deletions docs/core/store.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: Store
description: This doc describes core `jotai` bundle.
nav: 2.03
keywords: store,createstore,getdefaultstore,defaultstore
---

## createStore

This function is to create a new empty store.
The store can be used to pass in `Provider`.

The store has three methods: `get` for getting atom values,
`set` for setting atom values, and `sub` for subscribing to atom changes.

```jsx
const myStore = createStore()

const countAtom = atom(0)
myStore.set(countAtom, 1)
myStore.sub(countAtom, () => {
console.log('countAtom value is changed to', myStore.get(countAtom))
})

const Root = () => (
<Provider store={myStore}>
<App />
</Provider>
)
```

## getDefaultStore

This function returns a default store that is used in provider-less mode.

```js
const defaultStore = getDefaultStore()
```
Loading

1 comment on commit 932d82e

@vercel
Copy link

@vercel vercel bot commented on 932d82e Feb 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.