Skip to content

Commit

Permalink
docs(suspensive.org): add docs for @suspensive/jotai (#1084)
Browse files Browse the repository at this point in the history
# Overview

### Roadmap

- [x] motivation
- [x] installation
- [x] Atom
- [x] AtomValue
- [x] SetAtom
- [x] Translate

## PR Checklist

- [x] I did below actions if need

1. I read the [Contributing
Guide](https://github.com/toss/suspensive/blob/main/CONTRIBUTING.md)
2. I added documents and tests.

---------

Co-authored-by: jgjgill <79239852+jgjgill@users.noreply.github.com>
Co-authored-by: 김석진(poki) <102217654+SEOKKAMONI@users.noreply.github.com>
Co-authored-by: Jonghyeon Ko <jonghyeon@toss.im>
Co-authored-by: Jonghyeon Ko <61593290+manudeli@users.noreply.github.com>
  • Loading branch information
5 people authored Jul 18, 2024
1 parent 294d62a commit 597012c
Show file tree
Hide file tree
Showing 14 changed files with 594 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/suspensive.org/src/pages/docs/_meta.en.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
},
"react": "@suspensive/react",
"react-query": "@suspensive/react-query",
"jotai": "@suspensive/jotai",
"react-await": {
"title": "@suspensive/react-await",
"theme": {
Expand Down
1 change: 1 addition & 0 deletions docs/suspensive.org/src/pages/docs/_meta.ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
},
"react": "@suspensive/react",
"react-query": "@suspensive/react-query",
"jotai": "@suspensive/jotai",
"react-await": {
"title": "@suspensive/react-await",
"theme": {
Expand Down
108 changes: 108 additions & 0 deletions docs/suspensive.org/src/pages/docs/jotai/Atom.en.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { Callout } from '@/components'

# Atom

<Callout type='experimental'>

`<Atom/>` is an experimental feature, so this interface may change.

</Callout>

The Atom component provides an interface similar to Jotai's [useAtom](https://jotai.org/docs/core/use-atom#useatom) hook as props, allowing declarative usage.

### props.atom

You can use Jotai's atom as is.

```tsx /Atom/
import { Atom } from '@suspensive/jotai'
import { atom } from "jotai";

const countAtom = atom(1);

const Example = () => (
<Atom atom={countAtom}>
{([count, setCount]) => (
<>
<div>count: {count}</div>
<button onClick={() => setCount(count + 1)}>+1</button>
</>
)}
</Atom>
)
```

For Async Atom, it delegates the pending state of the Promise to the parent Suspense until the Promise resolves.

```tsx /Atom/
import { Atom } from '@suspensive/jotai'
import { Suspense } from '@suspensive/react'
import { atom } from "jotai";

const countAtom = atom(1)
const asyncDoubleCountAtom = atom(async (get) => {
await delay(2000)
return get(countAtom) * 2
})

const Example = () => (
<Suspense fallback={'pending...'}>
<Atom atom={asyncDoubleCountAtom}>
{([count]) => (
<>count: {count}</>
)}
</Atom>
</Suspense>
)
```

### Motivation

It's not immediately clear from the parent component which atoms are used internally in the child components and whether they trigger Suspense.

```tsx
// payment/page.tsx
import { Atom } from '@suspensive/jotai'
import { Suspense } from '@suspensive/react'
import { UserInfo, ShoppingCart } from '~/components'

const PaymentPage = () => (
<Suspense fallback={'pending...'}>
<UserInfo /> {/* It's not clear whether UserInfo internally triggers Suspense with an Async Atom. */}
<ShoppingCart /> {/* It's not clear whether ShoppingCart internally triggers Suspense with an Async Atom. */}
</Suspense>
)
```

```tsx
// payment/components/UserInfo.tsx
import { useAtomValue } from '@suspensive/jotai'
import { Suspense } from '@suspensive/react'
import { UserAddress } from '~/components'
import { userAsyncAtom } from "~/atoms";

// It's not clear from the usage of this component what Atom UserInfo uses internally and whether it triggers Suspense.
const UserInfo = () => {
const data = useAtomValue(userAsyncAtom)

return <UserAddress {...data} />
}
```

```tsx
// payment/components/ShoppingCart.tsx
import { Atom } from '@suspensive/jotai'
import { Suspense } from '@suspensive/react'
import { shoppingCartAtom } from "~/atoms";

// It's not clear from the usage of this component what Atom ShoppingCart uses internally and whether it triggers Suspense.
const ShoppingCart = () => {
const [data] = useAtom(shoppingCartAtom)

return (
<>
{data.map(item => <ShoppingItem key={item.id} {...item} />)}
</>
)
}
```
108 changes: 108 additions & 0 deletions docs/suspensive.org/src/pages/docs/jotai/Atom.ko.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { Callout } from '@/components'

# Atom

<Callout type='experimental'>

`<Atom/>`는 실험 기능이므로 이 인터페이스는 변경될 수 있습니다.

</Callout>

Atom 컴포넌트는 Jotai의 [useAtom](https://jotai.org/docs/core/use-atom#useatom) 훅과 동일한 인터페이스를 Props로 제공하며 선언적으로 사용할 수 있습니다.

### props.atom

Jotai의 atom을 그대로 사용할 수 있습니다.

```tsx /Atom/
import { Atom } from '@suspensive/jotai'
import { atom } from "jotai";

const countAtom = atom(1);

const Example = () => (
<Atom atom={countAtom}>
{([count, setCount]) => (
<>
<div>count: {count}</div>
<button onClick={() => setCount(count + 1)}>+1</button>
</>
)}
</Atom>
)
```

Async Atom일 경우 프로미스(Promise)가 해결(resolve) 되기 전까지, 부모의 Suspense에게 Promise의 pending 상태를 위임합니다.

```tsx /Atom/
import { Atom } from '@suspensive/jotai'
import { Suspense } from '@suspensive/react'
import { atom } from "jotai";

const countAtom = atom(1)
const asyncDoubleCountAtom = atom(async (get) => {
await delay(2000)
return get(countAtom) * 2
})

const Example = () => (
<Suspense fallback={'pending...'}>
<Atom atom={asyncDoubleCountAtom}>
{([count]) => (
<>count: {count}</>
)}
</Atom>
</Suspense>
)
```

### 동기

상위 컴포넌트에서 useAtom이 명확하게 드러나지 않습니다. 하위에 선언된 컴포넌트가 내부적으로 어떤 Atom을 사용하고, Suspense를 발생할지 예상하기 어렵습니다.

```tsx
// payment/page.tsx
import { Atom } from '@suspensive/jotai'
import { Suspense } from '@suspensive/react'
import { UserInfo, ShoppingCart } from '~/components'

const PaymentPage = () => (
<Suspense fallback={'pending...'}>
<UserInfo /> {/* UserInfo의 내부적으로 Suspense를 발생시키는 Async Atom을 사용하는지 예상하기 어렵습니다.*/}
<ShoppingCart /> {/* ShoppingCart의 내부적으로 Suspense를 발생시키는 Async Atom을 사용하는지 예상하기 어렵습니다. */}
</Suspense>
)
```

```tsx
// payment/components/UserInfo.tsx
import { useAtomValue } from '@suspensive/jotai'
import { Suspense } from '@suspensive/react'
import { UserAddress } from '~/components'
import { userAsyncAtom } from "~/atoms";

// 이 컴포넌트를 사용하는 입장에서 UserInfo라는 이름만으로 내부적으로 어떤 Atom을 사용하고, Suspense를 발생할지 예상하기 어렵습니다.
const UserInfo = () => {
const data = useAtomValue(userAsyncAtom)

return <UserAddress {...data} />
}
```

```tsx
// payment/components/ShoppingCart.tsx
import { Atom } from '@suspensive/jotai'
import { Suspense } from '@suspensive/react'
import { shoppingCartAtom } from "~/atoms";

// 이 컴포넌트를 사용하는 입장에서 ShoppingCart라는 이름만으로 내부적으로 어떤 Atom을 사용하고, Suspense를 발생할지 예상하기 어렵습니다.
const ShoppingCart = () => {
const [data] = useAtom(shoppingCartAtom)

return (
<>
{data.map(item => <ShoppingItem key={item.id} {...item} />)}
</>
)
}
```
58 changes: 58 additions & 0 deletions docs/suspensive.org/src/pages/docs/jotai/AtomValue.en.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Callout } from '@/components'

# AtomValue

<Callout type='experimental'>

`<AtomValue/>` is an experimental feature, so this interface may change.

</Callout>

The AtomValue component provides an interface similar to Jotai's [useAtomValue](https://jotai.org/docs/core/use-atom#useatomvalue) hook as props, allowing declarative usage.

### props.atom

You can use Jotai's atom as is.

```tsx /AtomValue/
import { AtomValue } from '@suspensive/jotai'
import { atom } from "jotai";

const countAtom = atom(1);

const Example = () => (
<AtomValue atom={countAtom}>
{(count) => (
<>count: {count}</>
)}
</AtomValue>
)
```

For Async Atom, it delegates the pending state of the Promise to the parent Suspense until the Promise resolves.

```tsx /AtomValue/
import { AtomValue } from '@suspensive/jotai'
import { Suspense } from '@suspensive/react'
import { atom } from "jotai";

const countAtom = atom(1)
const asyncDoubleCountAtom = atom(async (get) => {
await delay(2000)
return get(countAtom) * 2
})

const Example = () => (
<Suspense fallback={'pending...'}>
<AtomValue atom={asyncDoubleCountAtom}>
{(count) => (
<>count: {count}</>
)}
</AtomValue>
</Suspense>
)
```

### Motivation

Similar to [`<Atom/>`](https://suspensive.org/docs/jotai/Atom), `<AtomValue/>` also does not clearly reveal which atoms are used internally in child components and whether they trigger Suspense.
58 changes: 58 additions & 0 deletions docs/suspensive.org/src/pages/docs/jotai/AtomValue.ko.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Callout } from '@/components'

# AtomValue

<Callout type='experimental'>

`<AtomValue/>`는 실험 기능이므로 이 인터페이스는 변경될 수 있습니다.

</Callout>

AtomValue 컴포넌트는 Jotai의 [useAtomValue](https://jotai.org/docs/core/use-atom#useatomvalue) 훅과 동일한 인터페이스를 Props로 제공하며 선언적으로 사용할 수 있습니다.

### props.atom

Jotai의 atom을 그대로 사용할 수 있습니다.

```tsx /AtomValue/
import { AtomValue } from '@suspensive/jotai'
import { atom } from "jotai";

const countAtom = atom(1);

const Example = () => (
<AtomValue atom={countAtom}>
{(count) => (
<>count: {count}</>
)}
</AtomValue>
)
```

Async Atom일 경우 프로미스(Promise)가 해결(resolve) 되기 전까지, 부모의 Suspense에게 Promise의 pending 상태를 위임합니다.

```tsx /AtomValue/
import { AtomValue } from '@suspensive/jotai'
import { Suspense } from '@suspensive/react'
import { atom } from "jotai";

const countAtom = atom(1)
const asyncDoubleCountAtom = atom(async (get) => {
await delay(2000)
return get(countAtom) * 2
})

const Example = () => (
<Suspense fallback={'pending...'}>
<AtomValue atom={asyncDoubleCountAtom}>
{(count) => (
<>count: {count}</>
)}
</AtomValue>
</Suspense>
)
```

### 동기

[`<Atom/>`](https://suspensive.org/ko/docs/jotai/Atom)의 동기와 같이 `<AtomValue/>` 또한, 상위 컴포넌트에서 명확하게 드러나지 않습니다. 하위에 선언된 컴포넌트가 내부적으로 어떤 Atom을 사용하고, Suspense를 발생할지 예상하기 어렵습니다.
Loading

0 comments on commit 597012c

Please sign in to comment.