Skip to content

Commit

Permalink
Merge pull request #933 from artalar/devtools-graph-view
Browse files Browse the repository at this point in the history
Devtools graph view
  • Loading branch information
artalar authored Oct 8, 2024
2 parents 449dd17 + ea8194b commit 32c52f0
Show file tree
Hide file tree
Showing 24 changed files with 1,518 additions and 321 deletions.
22 changes: 15 additions & 7 deletions examples/model/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,21 @@ import {
withRetry,
withAssign,
action,
withComputed,
isInit,
} from '@reatom/framework'
import { withSearchParamsPersist } from '@reatom/url'
import { withLocalStorage } from '@reatom/persist-web-storage'

export const searchAtom = atom('', 'searchAtom')
export const searchAtom = atom('', 'searchAtom').pipe(withSearchParamsPersist('search'))

export const pageAtom = atom(1, 'pageAtom').pipe(
withComputed((ctx, state) => {
// reset the state on other filters change
ctx.spy(searchAtom)
// check the init to do not drop the persist state
return isInit(ctx) ? state : 1
}),
withSearchParamsPersist('page', (page) => Number(page || 1)),
withAssign((target, name) => ({
next: action((ctx) => target(ctx, (page) => page + 1), `${name}.next`),
Expand All @@ -22,6 +31,7 @@ export const pageAtom = atom(1, 'pageAtom').pipe(
)

export const issuesResource = reatomResource(async (ctx) => {
const { signal } = ctx.controller
const query = ctx.spy(searchAtom)
const page = ctx.spy(pageAtom)

Expand All @@ -30,12 +40,12 @@ export const issuesResource = reatomResource(async (ctx) => {
// debounce
await ctx.schedule(() => sleep(350))

const { items } = await api.searchIssues({ query, page, signal: ctx.controller.signal })
const { items } = await api.searchIssues({ query, page, signal })
return items
}, 'issues').pipe(
withDataAtom([]),
withErrorAtom(),
withCache({ length: Infinity, swr: false, staleTime: 3 * 60 * 1000 }),
withCache({ length: Infinity, swr: false, staleTime: 3 * 60 * 1000, withPersist: withLocalStorage }),
withRetry({
onReject(ctx, error, retries) {
if (error instanceof Error && error?.message.includes('rate limit')) {
Expand Down Expand Up @@ -90,10 +100,8 @@ export const api = {
perPage?: number
signal: AbortSignal
}): Promise<IssuesResponse> {
const response = await fetch(
`https://api.github.com/search/issues?q=${query}&page=${page}&per_page=${perPage}`,
{ signal },
)
const url = `https://api.github.com/search/issues?q=${query}&page=${page}&per_page=${perPage}`
const response = await fetch(url, { signal })

if (response.status !== 200) {
const error = new Error(`HTTP Error: ${response.statusText}`)
Expand Down
1 change: 1 addition & 0 deletions examples/react-search/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"preview": "vite preview"
},
"dependencies": {
"@reatom/devtools": "*",
"@reatom/framework": "^3.*.*",
"@reatom/npm-react": "^3.*.*",
"react": "^18.2.0",
Expand Down
12 changes: 8 additions & 4 deletions examples/react-search/src/app.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { reatomComponent } from '@reatom/npm-react'
import { searchAtom, issuesResource } from './model'
import { searchAtom, issuesResource, pageAtom } from './model'

export const App = reatomComponent(({ ctx }) => {
const isLoading = Boolean(
ctx.spy(issuesResource.pendingAtom) || ctx.spy(issuesResource.retriesAtom),
)
const isLoading = Boolean(ctx.spy(issuesResource.pendingAtom) || ctx.spy(issuesResource.retriesAtom))
const page = ctx.spy(pageAtom)

return (
<main>
Expand All @@ -13,6 +12,11 @@ export const App = reatomComponent(({ ctx }) => {
onChange={(e) => searchAtom(ctx, e.currentTarget.value)}
placeholder="Search"
/>
<button disabled={!page} onClick={() => pageAtom(ctx, (s) => s - 1)}>
{'<'}
</button>
{page}
<button onClick={() => pageAtom(ctx, (s) => s + 1)}>{'>'}</button>
{isLoading && 'Loading...'}
<ul>
{ctx.spy(issuesResource.dataAtom).map(({ title }, i) => (
Expand Down
11 changes: 5 additions & 6 deletions examples/react-search/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import { createCtx, connectLogger } from '@reatom/framework'
import { connectDevtools } from '@reatom/devtools'
import { reatomContext } from '@reatom/npm-react'
import { App } from './app'

const ctx = createCtx()

connectLogger(ctx)
connectDevtools(ctx)

const root = ReactDOM.createRoot(document.getElementById('root')!)
root.render(
<React.StrictMode>
<reatomContext.Provider value={ctx}>
<App />
</reatomContext.Provider>
</React.StrictMode>,
<reatomContext.Provider value={ctx}>
<App />
</reatomContext.Provider>,
)
2 changes: 1 addition & 1 deletion packages/async/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
},
"dependencies": {
"@reatom/core": "^3.5.0",
"@reatom/effects": "^3.7.0",
"@reatom/effects": "^3.10.0",
"@reatom/hooks": "^3.2.0",
"@reatom/primitives": "^3.5.0",
"@reatom/utils": "^3.4.0"
Expand Down
44 changes: 19 additions & 25 deletions packages/async/src/withCache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ import { reatomAsync, withAbort, withDataAtom, withCache, AsyncCtx } from './'
const test = suite('withCache')

test('withCache', async () => {
const fetchData = reatomAsync(
async (ctx, { a, b }: { a: number; b: number }) => a,
).pipe(withDataAtom(0), withCache())
const fetchData = reatomAsync(async (ctx, { a, b }: { a: number; b: number }) => a).pipe(withDataAtom(0), withCache())
const ctx = createTestCtx()

await fetchData(ctx, { a: 400, b: 0 })
Expand Down Expand Up @@ -57,10 +55,7 @@ test('withCache dataAtom mapper', async () => {

test('withCache swr true (default)', async () => {
let i = 0
const fetchData = reatomAsync((ctx) => Promise.resolve(++i)).pipe(
withDataAtom(0),
withCache(),
)
const fetchData = reatomAsync((ctx) => Promise.resolve(++i)).pipe(withDataAtom(0), withCache())

const ctx = createTestCtx()
const track = ctx.subscribeTrack(fetchData.dataAtom)
Expand Down Expand Up @@ -139,11 +134,7 @@ test('withCache withAbort vary params', async () => {

return n
})
const fetchData = reatomAsync(effect).pipe(
withDataAtom(0),
withCache(),
withAbort(),
)
const fetchData = reatomAsync(effect).pipe(withDataAtom(0), withCache(), withAbort())

const ctx = createTestCtx()
const track = ctx.subscribeTrack(fetchData.dataAtom)
Expand Down Expand Up @@ -201,11 +192,7 @@ test('withCache withAbort same params', async () => {

test('withCache and action mocking', async () => {
const effect = mockFn(async (ctx: any, n: number) => n)
const fetchData = reatomAsync(effect).pipe(
withDataAtom(0),
withCache(),
withAbort(),
)
const fetchData = reatomAsync(effect).pipe(withDataAtom(0), withCache(), withAbort())
const ctx = createTestCtx()

ctx.mockAction(fetchData, async (ctx, n) => n * 10)
Expand Down Expand Up @@ -257,10 +244,7 @@ test('do not cache aborted promise', async () => {
ctx.controller.signal.throwIfAborted()
return 1
})
const fetchData = reatomAsync(effect).pipe(
withDataAtom(0),
withCache({ ignoreAbort: false }),
)
const fetchData = reatomAsync(effect).pipe(withDataAtom(0), withCache({ ignoreAbort: false }))
onConnect(fetchData.dataAtom, fetchData)
const ctx = createTestCtx()

Expand All @@ -281,10 +265,7 @@ test('do not cache aborted promise', async () => {

test('should be able to manage cache manually', async () => {
const effect = mockFn(async (ctx: any, n: number) => n)
const fetchData = reatomAsync(effect).pipe(
withDataAtom(0),
withCache({ swr: false }),
)
const fetchData = reatomAsync(effect).pipe(withDataAtom(0), withCache({ swr: false }))
const ctx = createTestCtx()

fetchData(ctx, 1)
Expand All @@ -308,4 +289,17 @@ test('should be able to manage cache manually', async () => {
assert.is(effect.calls.length, 2)
})

test('Infinity cache invalidation', async () => {
const effect = mockFn(async (ctx: any, n: number) => n)
const fetchData = reatomAsync(effect).pipe(withDataAtom(0), withCache({ swr: false, staleTime: Infinity }))
const ctx = createTestCtx()

await fetchData(ctx, 1)
await fetchData(ctx, 2)
assert.is(effect.calls.length, 2)

await fetchData.cacheAtom.invalidate(ctx)
assert.is(effect.calls.length, 3)
})

test.run()
Loading

0 comments on commit 32c52f0

Please sign in to comment.