-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chroe: update
- Loading branch information
Showing
15 changed files
with
415 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
import React, { useRef, useMemo, memo } from 'react' | ||
import useSWR, { unstable_serialize } from 'swr' | ||
import { | ||
createCacheHelper, | ||
SWRHook, | ||
Middleware, | ||
withMiddleware, | ||
isUndefined, | ||
useIsomorphicLayoutEffect, | ||
mergeObjects, | ||
MutatorOptions, | ||
MutatorCallback, | ||
Arguments, | ||
RevalidatorOptions, | ||
SWRGlobalState, | ||
getTimestamp, | ||
GlobalState, | ||
BareFetcher, | ||
defaultConfig | ||
} from 'swr/_internal' | ||
|
||
import type { | ||
SWRItemProps, | ||
SWRAggregatorConfiguration, | ||
SWRAggregator, | ||
SWRCollection | ||
} from './types' | ||
|
||
const defaultChildren = () => { | ||
return null | ||
} | ||
|
||
export const aggregator = (<Data, Error, Key extends Arguments = Arguments>( | ||
useSWRNext: SWRHook | ||
) => | ||
( | ||
_keys: Key[], | ||
fetcher: BareFetcher<Data>, | ||
config: typeof defaultConfig & SWRAggregatorConfiguration<Data, Error, Key> | ||
) => { | ||
if (!Array.isArray(_keys)) throw new Error('not array') | ||
const { cache, compare, mutate: _internalMutate } = config | ||
const fetcherRef = useRef(fetcher) | ||
const configRef = useRef(config) | ||
const swrkeys = unstable_serialize(_keys) | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
const keys = useMemo(() => _keys.map(v => unstable_serialize(v)), [swrkeys]) | ||
const cacheHelpers = useMemo( | ||
() => | ||
keys.map(key => { | ||
const [get] = createCacheHelper<Data>(cache, key) | ||
return { | ||
get | ||
} | ||
}), | ||
[keys, cache] | ||
) | ||
const fetch = async (revalidateOpts?: RevalidatorOptions): Promise<any> => { | ||
const revalidate = async (index: number) => { | ||
let newData: Data | ||
let startAt: number | ||
const opts = revalidateOpts || {} | ||
const key = keys[index] | ||
const _key = _keys[index] | ||
const { get } = cacheHelpers[index] | ||
const [_, MUTATION, FETCH] = SWRGlobalState.get(cache) as GlobalState | ||
// If there is no ongoing concurrent request, or `dedupe` is not set, a | ||
// new request should be initiated. | ||
const shouldStartNewRequest = !FETCH[key] || !opts.dedupe | ||
|
||
const cleanupState = () => { | ||
// Check if it's still the same request before deleting. | ||
const requestInfo = FETCH[key] | ||
if (requestInfo && requestInfo[1] === startAt) { | ||
delete FETCH[key] | ||
} | ||
} | ||
const currentFetcher = fetcherRef.current | ||
try { | ||
if (shouldStartNewRequest) { | ||
FETCH[key] = [currentFetcher(_key), getTimestamp()] | ||
} | ||
;[newData, startAt] = FETCH[key] | ||
newData = await newData | ||
|
||
if (shouldStartNewRequest) { | ||
setTimeout(cleanupState, config.dedupingInterval) | ||
} | ||
const mutationInfo = MUTATION[key] | ||
if ( | ||
!isUndefined(mutationInfo) && | ||
// case 1 | ||
(startAt <= mutationInfo[0] || | ||
// case 2 | ||
startAt <= mutationInfo[1] || | ||
// case 3 | ||
mutationInfo[1] === 0) | ||
) { | ||
return mergeObjects({}, { data: get().data, error: get().error }) | ||
} | ||
if (!compare(newData, get().data)) { | ||
await _internalMutate(_key, newData, false) | ||
} | ||
// eslint-disable-next-line no-empty | ||
} catch { | ||
cleanupState() | ||
} | ||
return mergeObjects({}, { data: get().data, error: get().error }) | ||
} | ||
return Promise.all(keys.map((___, i) => revalidate(i))) | ||
} | ||
const swr = useSWRNext(_keys, () => fetch({ dedupe: true }), config) | ||
const SWRAggregatorItem = useMemo(() => { | ||
const Component = memo(({ index }: { index: number }) => { | ||
const item = useSWR(_keys[index], async () => { | ||
const currentFetcher = fetcherRef.current | ||
const data = await currentFetcher(_keys[index]) | ||
swr.mutate() | ||
return data | ||
}) | ||
const children = configRef.current.children || defaultChildren | ||
return children(item, swr, index) | ||
}) | ||
Component.displayName = 'SWRAggregatorItem' | ||
return Component | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [keys, swr]) | ||
const item = (key: any, index: number) => ( | ||
<SWRAggregatorItem key={key} index={index} /> | ||
) | ||
useIsomorphicLayoutEffect(() => { | ||
fetcherRef.current = fetcher | ||
configRef.current = config | ||
}) | ||
return { | ||
items: keys.map(item), | ||
mutate: ( | ||
data: Data[] | Promise<Data[]> | MutatorCallback<Data[]> = () => | ||
fetch({ dedupe: false }), | ||
opt: boolean | MutatorOptions<Data[]> = false | ||
) => swr.mutate(data, opt), | ||
get data() { | ||
return swr.data?.map((v: any, i: number) => | ||
mergeObjects(v, { | ||
key: keys[i], | ||
originKey: _keys[i] | ||
}) | ||
) | ||
}, | ||
get isLoading() { | ||
return swr.isLoading | ||
}, | ||
get isValidating() { | ||
return swr.isValidating | ||
} | ||
} | ||
}) as unknown as Middleware | ||
|
||
export default withMiddleware(useSWR, aggregator) as unknown as SWRAggregator | ||
|
||
export { | ||
SWRItemProps, | ||
SWRAggregatorConfiguration, | ||
SWRAggregator, | ||
SWRCollection | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
"name": "swr-aggregator", | ||
"version": "0.0.1", | ||
"main": "./dist/index.js", | ||
"module": "./dist/index.esm.js", | ||
"types": "./dist/aggregator", | ||
"exports": "./dist/index.mjs", | ||
"private": true, | ||
"scripts": { | ||
"watch": "bunchee index.tsx --no-sourcemap -w", | ||
"build": "bunchee index.tsx --no-sourcemap", | ||
"types:check": "tsc --noEmit", | ||
"clean": "rimraf dist" | ||
}, | ||
"peerDependencies": { | ||
"swr": "*", | ||
"react": "*", | ||
"use-sync-external-store": "*" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"extends": "../tsconfig.json", | ||
"compilerOptions": { | ||
"rootDir": "..", | ||
"outDir": "./dist" | ||
}, | ||
"include": ["./*.tsx"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import { | ||
SWRConfiguration, | ||
Arguments, | ||
BareFetcher, | ||
KeyedMutator, | ||
Fetcher, | ||
SWRResponse | ||
} from 'swr/_internal' | ||
|
||
export type Keys<T extends Arguments = Arguments> = T[] | ||
|
||
export interface SWRCollection< | ||
Data = any, | ||
Error = any, | ||
Key extends Arguments = Arguments | ||
> { | ||
mutate: KeyedMutator<Data[]> | ||
data?: Array<{ | ||
data?: Data | ||
error?: Error | ||
key: string | ||
originKey: Key | ||
}> | ||
isValidating: boolean | ||
isLoading: boolean | ||
} | ||
|
||
export interface SWRItemProps<Data = any, Key extends Arguments = Arguments> { | ||
keys: Key[] | ||
fetcher: BareFetcher<Data> | ||
index: number | ||
} | ||
|
||
export interface SWRAggregatorConfiguration< | ||
Data = any, | ||
Error = any, | ||
OriginKey extends Arguments = Arguments | ||
> extends SWRConfiguration<Data, Error> { | ||
children: ( | ||
items: SWRResponse<Data, Error>, | ||
collection: SWRCollection<Data, Error, OriginKey>, | ||
index: number | ||
) => React.ReactElement<any, any> | null | ||
} | ||
|
||
interface AggregatorResult< | ||
Data = any, | ||
Error = any, | ||
Key extends Arguments = Arguments | ||
> extends SWRCollection<Data, Error, Key> { | ||
items: Array<JSX.Element | null> | ||
} | ||
|
||
export interface SWRAggregator { | ||
<Data = any, Error = any, Key extends Arguments = Arguments>( | ||
key: Keys<Key> | ||
): AggregatorResult<Data, Error> | ||
<Data = any, Error = any, Key extends Arguments = Arguments>( | ||
key: Keys<Key>, | ||
fetcher: Fetcher<Data, Key> | null | ||
): AggregatorResult<Data, Error> | ||
<Data = any, Error = any, Key extends Arguments = Arguments>( | ||
key: Keys<Key>, | ||
config: SWRAggregatorConfiguration<Data, Error, Key> | undefined | ||
): AggregatorResult<Data, Error> | ||
<Data = any, Error = any, Key extends Arguments = Arguments>( | ||
key: Keys<Key>, | ||
fetcher: Fetcher<Data, Key> | null, | ||
config: SWRAggregatorConfiguration<Data, Error, Key> | undefined | ||
): AggregatorResult<Data, Error> | ||
<Data = any, Error = any>(key: Keys): AggregatorResult<Data, Error> | ||
<Data = any, Error = any>( | ||
key: Keys, | ||
fetcher: BareFetcher<Data> | null | ||
): AggregatorResult<Data, Error> | ||
<Data = any, Error = any>( | ||
key: Keys, | ||
config: SWRAggregatorConfiguration<Data, Error> | undefined | ||
): AggregatorResult<Data, Error> | ||
<Data = any, Error = any>( | ||
key: Keys, | ||
fetcher: BareFetcher<Data> | null, | ||
config: SWRAggregatorConfiguration<Data, Error> | undefined | ||
): AggregatorResult<Data, Error> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Basic | ||
|
||
## One-Click Deploy | ||
|
||
Deploy your own SWR project with Vercel. | ||
|
||
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?s=https://github.com/vercel/swr/tree/main/examples/basic) | ||
|
||
## How to Use | ||
|
||
Download the example: | ||
|
||
```bash | ||
curl https://codeload.github.com/vercel/swr/tar.gz/main | tar -xz --strip=2 swr-main/examples/basic | ||
cd basic | ||
``` | ||
|
||
Install it and run: | ||
|
||
```bash | ||
yarn | ||
yarn dev | ||
# or | ||
npm install | ||
npm run dev | ||
``` | ||
|
||
## The Idea behind the Example | ||
|
||
Show a basic usage of SWR fetching data from an API in two different pages. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export default async function fetcher(...args) { | ||
const res = await fetch(...args) | ||
return res.json() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"name": "queries", | ||
"private": true, | ||
"license": "MIT", | ||
"dependencies": { | ||
"next": "latest", | ||
"react": "18.1.0", | ||
"react-dom": "18.1.0", | ||
"swr": "latest" | ||
}, | ||
"scripts": { | ||
"dev": "next", | ||
"start": "next start", | ||
"build": "next build" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
const projects = [ | ||
'facebook/flipper', | ||
'vuejs/vuepress', | ||
'rust-lang/rust', | ||
'vercel/next.js' | ||
] | ||
|
||
export default async function api(req, res) { | ||
if (req.query.id) { | ||
return new Promise(resolve => { | ||
setTimeout(() => resolve(projects[req.query.id]), 1500) | ||
}).then(v => res.json(v)) | ||
} | ||
} |
Oops, something went wrong.