Skip to content

Commit

Permalink
refactor(async): use reatomResource instead of reatomAsyncReaction
Browse files Browse the repository at this point in the history
  • Loading branch information
BANOnotIT committed Oct 19, 2023
1 parent 7e8bbf1 commit 751d822
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 35 deletions.
18 changes: 9 additions & 9 deletions packages/async/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ const reatomResource = (initState, url, concurrent = true) => {

Check the real-world example in pooling example from [story tests below](https://www.reatom.dev/package/async#story-test) ([src](https://github.com/artalar/reatom/blob/v3/packages/async/src/index.story.test.ts)).

## reatomReactiveAsync
## reatomResource

This method is the simplest solution to describe an asynchronous resource that is based on local states. Let's delve into the problem.

Expand All @@ -660,12 +660,12 @@ onConnect(fetchList.dataAtom, (ctx) => fetchList(ctx, ctx.get(pageAtom)))
pageAtom.onChange(fetchSuggestion) // trigger
```

`reatomReactiveAsync` allows us to use `ctx.spy` just like in the regular `atom`. It is much simpler, more obvious, and works automatically for both caching and previous request cancellation.
`reatomResource` allows us to use `ctx.spy` just like in the regular `atom`. It is much simpler, more obvious, and works automatically for both caching and previous request cancellation.

```ts
import { reatomReactiveAsync } from '@reatom/async'
import { reatomResource } from '@reatom/async'

const listReaction = reatomReactiveAsync(async (ctx) => {
const listReaction = reatomResource(async (ctx) => {
const page = ctx.spy(pageAtom)
return request(`/api/list?page=${page}`, ctx.controller)
}, 'listReaction')
Expand All @@ -675,16 +675,16 @@ Now, `listReaction` has a `promiseAtom` that you can use with [useAtomPromise](h

If you need to set up a default value and have the ability to use the resulting data, simply use `withDataAtom` as you would with any other async action.

But that's not all! The most powerful feature of `reatomReactiveAsync` is that you can use one `promiseAtom` in another, which greatly simplifies dependent request descriptions and prevents complex race conditions, as the stale promises are always automatically canceled.
But that's not all! The most powerful feature of `reatomResource` is that you can use one `promiseAtom` in another, which greatly simplifies dependent request descriptions and prevents complex race conditions, as the stale promises are always automatically canceled.

```ts
import { reatomReactiveAsync } from '@reatom/async'
import { reatomResource } from '@reatom/async'

const aReaction = reatomReactiveAsync(async (ctx) => {
const aReaction = reatomResource(async (ctx) => {
const page = ctx.spy(pageAtom)
return request(`/api/a?page=${page}`, ctx.controller)
}, 'aReaction')
const bReaction = reatomReactiveAsync(async (ctx) => {
const bReaction = reatomResource(async (ctx) => {
const a = ctx.spy(aReaction.promiseAtom)
return request(`/api/b?a=${a}`, ctx.controller)
}, 'bReaction')
Expand All @@ -694,4 +694,4 @@ In this example, `bReaction.pendingAtom` will be updated immediately as `aReacti

## reatomAsyncReaction

> Deprecated: use [reatomReactiveAsync](#reatomreactiveasync) instead
> Deprecated: use [reatomResource](#reatomresource) instead
2 changes: 1 addition & 1 deletion packages/async/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import './index.story.test'
import './withCache.test'
import './withStatusesAtom.test'
import './mapToAsync.test'
import './reatomReactiveAsync.test'
import './reatomResource.test'

test(`base API`, async () => {
const fetchData = reatomAsync(async (ctx, v: number) => {
Expand Down
6 changes: 3 additions & 3 deletions packages/async/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ export type {
export {
reatomAsyncReaction,
AsyncReaction,
ReactiveAsync,
reatomReactiveAsync,
} from './reatomReactiveAsync'
ResourceAtom,
reatomResource,
} from './reatomResource'

export interface AsyncAction<Params extends any[] = any[], Resp = any>
extends Action<Params, ControlledPromise<Resp>> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@ import { suite } from 'uvu'
import * as assert from 'uvu/assert'
import { createTestCtx, mockFn } from '@reatom/testing'
import { atom } from '@reatom/core'
import { reatomReactiveAsync } from './reatomReactiveAsync'
import { reatomResource } from './reatomResource'
import { noop, sleep } from '@reatom/utils'
import { withCache, withDataAtom, withErrorAtom, withRetry } from '.'
import { isConnected } from '@reatom/hooks'

export const test = suite('reatomReactiveAsync')
export const test = suite('reatomResource')

test('base', async () => {
const paramsAtom = atom(0, 'paramsAtom')
const async1 = reatomReactiveAsync(async (ctx) => {
const async1 = reatomResource(async (ctx) => {
const argument = ctx.spy(paramsAtom)
await ctx.schedule(() => sleep())
return argument
}, 'async1').promiseAtom
const async2 = reatomReactiveAsync(async (ctx) => {
const async2 = reatomResource(async (ctx) => {
const n = await ctx.spy(async1)
return n
}, 'async2').promiseAtom
Expand All @@ -40,12 +40,12 @@ test('base', async () => {
test('withCache', async () => {
const sleepTrack = mockFn(sleep)
const paramsAtom = atom(0, 'paramsAtom')
const aAtom = reatomReactiveAsync(async (ctx) => {
const aAtom = reatomResource(async (ctx) => {
const argument = ctx.spy(paramsAtom)
await ctx.schedule(() => sleepTrack())
return argument
}, 'aAtom').pipe(withCache())
const bAtom = reatomReactiveAsync(async (ctx) => {
const bAtom = reatomResource(async (ctx) => {
const n = await ctx.spy(aAtom.promiseAtom)
return n
}, 'bAtom')
Expand Down Expand Up @@ -77,7 +77,7 @@ test('withCache', async () => {
test('controller', async () => {
const controllerTrack = mockFn()
const paramsAtom = atom(0, 'paramsAtom')
const someReaction = reatomReactiveAsync(async (ctx) => {
const someReaction = reatomResource(async (ctx) => {
const argument = ctx.spy(paramsAtom)
ctx.controller.signal.addEventListener('abort', controllerTrack)
await ctx.schedule(() => sleep())
Expand All @@ -103,7 +103,7 @@ test('controller', async () => {

test('withDataAtom', async () => {
const paramsAtom = atom(0, 'paramsAtom')
const someReaction = reatomReactiveAsync(async (ctx) => {
const someReaction = reatomResource(async (ctx) => {
const params = ctx.spy(paramsAtom)
await ctx.schedule(() => sleep())
return params
Expand All @@ -121,7 +121,7 @@ test('withDataAtom', async () => {
test('withErrorAtom withRetry', async () => {
let shouldThrow = true
const paramsAtom = atom(123, 'paramsAtom')
const someReaction = reatomReactiveAsync(async (ctx) => {
const someReaction = reatomResource(async (ctx) => {
const params = ctx.spy(paramsAtom)
if (shouldThrow) throw new Error('test error')
await ctx.schedule(() => sleep())
Expand Down Expand Up @@ -155,7 +155,7 @@ test('withErrorAtom withRetry', async () => {

test('abort should not stale', async () => {
const paramsAtom = atom(123, 'paramsAtom')
const someReaction = reatomReactiveAsync(async (ctx) => {
const someReaction = reatomResource(async (ctx) => {
const params = ctx.spy(paramsAtom)
await ctx.schedule(() => sleep())
return params
Expand All @@ -172,7 +172,7 @@ test('abort should not stale', async () => {

test('direct retry', async () => {
const paramsAtom = atom(123, 'paramsAtom')
const someReaction = reatomReactiveAsync(async (ctx) => {
const someReaction = reatomResource(async (ctx) => {
ctx.spy(paramsAtom)
await ctx.schedule(() => calls++)
}, 'someReaction')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ import { merge, noop, toAbortError } from '@reatom/utils'
import { reatomAsync, AsyncAction, ControlledPromise, AsyncCtx } from '.'
import { isConnected, onConnect } from '@reatom/hooks'

export interface ReactiveAsync<Resp> extends AsyncAction<[], Resp> {
export interface ResourceAtom<Resp> extends AsyncAction<[], Resp> {
promiseAtom: Atom<ControlledPromise<Resp>>
}

/**
* @deprecated use ReactiveAsync instead
* @deprecated use ResourceAtom instead
*/
export interface AsyncReaction<Resp> extends ReactiveAsync<Resp> {}
export interface AsyncReaction<Resp> extends ResourceAtom<Resp> {}

export interface AsyncCtxSpy extends AsyncCtx {
spy: {
Expand All @@ -30,10 +30,10 @@ export interface AsyncCtxSpy extends AsyncCtx {

const resolved = new Set<Promise<any>>()

export const reatomReactiveAsync = <T>(
export const reatomResource = <T>(
asyncComputed: (ctx: AsyncCtxSpy) => Promise<T>,
name = __count('asyncAtom'),
): ReactiveAsync<T> => {
): ResourceAtom<T> => {
const promises = new CauseContext<Promise<any>>()

const dropCache = (ctx: Ctx) =>
Expand Down Expand Up @@ -161,7 +161,7 @@ export const reatomReactiveAsync = <T>(
},
theAsync,
{ promiseAtom },
) as ReactiveAsync<T>
) as ResourceAtom<T>

Object.defineProperty(theAsync, '_handleCache', {
get() {
Expand All @@ -173,6 +173,6 @@ export const reatomReactiveAsync = <T>(
}

/**
* @deprecated use reatomReactiveAsync instead
* @deprecated use reatomResource instead
*/
export const reatomAsyncReaction = reatomReactiveAsync
export const reatomAsyncReaction = reatomResource
6 changes: 3 additions & 3 deletions packages/npm-react/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,14 +264,14 @@ export const MyForm = () => {
## Use atom promise
If you have an atom with a promise and want to use its value directly, you could use `useAtomPromise`. This function relies on [React Suspense](https://react.dev/reference/react/Suspense) and throws the promise until it resolves. It can be useful with [reatomReactiveAsync](https://www.reatom.dev/package/async/#reatomreactiveasync).
If you have an atom with a promise and want to use its value directly, you could use `useAtomPromise`. This function relies on [React Suspense](https://react.dev/reference/react/Suspense) and throws the promise until it resolves. It can be useful with [reatomResource](https://www.reatom.dev/package/async/#reatomresource).
```tsx
import { atom, reatomReactiveAsync } from '@reatom/framework'
import { atom, reatomResource } from '@reatom/framework'
import { useAtom, useAction, useAtomPromise } from '@reatom/npm-react'

const pageAtom = atom(1, 'pageAtom')
const listReaction = reatomReactiveAsync(async (ctx) => {
const listReaction = reatomResource(async (ctx) => {
const page = ctx.spy(pageAtom)
const response = await ctx.schedule(() => fetch(`/api/list?page=${page}`))
if (!response.ok) throw new Error(response.statusText)
Expand Down

0 comments on commit 751d822

Please sign in to comment.