react-streaming
Advanced tools
Comparing version 0.3.0 to 0.3.1
export { useAsync }; | ||
declare function useAsync<T>(keyValue: unknown, asyncFn: () => Promise<T>): T; | ||
declare function useAsync<T>(keyValue: unknown, asyncFn: () => T): Awaited<T>; |
@@ -25,3 +25,3 @@ "use strict"; | ||
(0, utils_1.assert)(suspenses); | ||
return (0, useSuspense_1.useSuspense)({ suspenses, resolver, key, elementId }); | ||
return (0, useSuspense_1.useSuspense)({ suspenses, resolver, key, elementId, asyncFnName: asyncFn.name }); | ||
} | ||
@@ -28,0 +28,0 @@ exports.useAsync = useAsync; |
@@ -16,11 +16,12 @@ export { useSuspense }; | ||
}; | ||
declare function useSuspense<T>({ key, elementId, suspenses, resolver, resolverSync, needsWorkaround }: { | ||
declare function useSuspense<T>({ key, elementId, suspenses, resolver, resolverSync, needsWorkaround, asyncFnName }: { | ||
key: string; | ||
elementId: string; | ||
suspenses: Suspenses; | ||
resolver: () => Promise<T>; | ||
resolver: () => T; | ||
resolverSync?: () => null | { | ||
value: T; | ||
value: Awaited<T>; | ||
}; | ||
needsWorkaround?: true; | ||
}): T; | ||
asyncFnName: string; | ||
}): Awaited<T>; |
@@ -12,3 +12,3 @@ "use strict"; | ||
//*/ | ||
function useSuspense({ key, elementId, suspenses, resolver, resolverSync, needsWorkaround }) { | ||
function useSuspense({ key, elementId, suspenses, resolver, resolverSync, needsWorkaround, asyncFnName }) { | ||
DEBUG && console.log('=== useSuspense()'); | ||
@@ -51,3 +51,3 @@ const suspenseId = getSuspenseId(key, elementId); | ||
{ | ||
const updateSuspense = (s) => { | ||
const updateSuspenseAsync = (s) => { | ||
suspense = s; | ||
@@ -74,10 +74,20 @@ if (!needsWorkaround) { | ||
DEBUG && console.log('resolver()'); | ||
promise.then((value) => { | ||
updateSuspense({ state: 'done', value }); | ||
DEBUG && console.log('=== resolver() done', suspense); | ||
}); | ||
updateSuspense({ state: 'pending', promise }); | ||
if (!(0, utils_1.isPromise)(promise)) { | ||
const fnName = asyncFnName || 'fn'; | ||
(0, utils_1.assertWarning)(false, `[useAsync(key, ${fnName})] You provided a function \`${fnName}\` which didn't return a promise`, { | ||
onlyOnce: true, | ||
showStackTrace: true | ||
}); | ||
suspense = suspenses[suspenseId] = { state: 'done', value: promise }; | ||
} | ||
else { | ||
promise.then((value) => { | ||
updateSuspenseAsync({ state: 'done', value }); | ||
DEBUG && console.log('=== resolver() done', suspense); | ||
}); | ||
updateSuspenseAsync({ state: 'pending', promise }); | ||
} | ||
} | ||
catch (err) { | ||
updateSuspense({ state: 'error', err }); | ||
updateSuspenseAsync({ state: 'error', err }); | ||
} | ||
@@ -84,0 +94,0 @@ (0, utils_1.assert)(suspense); |
export * from '../utils/assert'; | ||
export * from '../utils/getGlobalVariable'; | ||
export * from '../utils/isPromise'; |
@@ -19,1 +19,2 @@ "use strict"; | ||
__exportStar(require("../utils/getGlobalVariable"), exports); | ||
__exportStar(require("../utils/isPromise"), exports); |
@@ -6,3 +6,3 @@ "use strict"; | ||
const projectInfo_1 = require("./projectInfo"); | ||
const errorPrefix = `[${projectInfo_1.projectInfo.npmPackageName}]`; | ||
const errorPrefix = `[${projectInfo_1.projectInfo.npmPackageName}@${projectInfo_1.projectInfo.projectVersion}]`; | ||
const internalErrorPrefix = `${errorPrefix}[Bug]`; | ||
@@ -9,0 +9,0 @@ const usageErrorPrefix = `${errorPrefix}[Wrong Usage]`; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.projectInfo = void 0; | ||
const PROJECT_VERSION = '0.3.0'; | ||
const PROJECT_VERSION = '0.3.1'; | ||
exports.projectInfo = { | ||
@@ -6,0 +6,0 @@ projectName: 'react-streaming', |
export { useAsync }; | ||
declare function useAsync<T>(keyValue: unknown, asyncFn: () => Promise<T>): T; | ||
declare function useAsync<T>(keyValue: unknown, asyncFn: () => T): Awaited<T>; |
@@ -25,3 +25,11 @@ export { useAsync }; | ||
}; | ||
return useSuspense({ suspenses, resolver, resolverSync, key, elementId, needsWorkaround: true }); | ||
return useSuspense({ | ||
suspenses, | ||
resolver, | ||
resolverSync, | ||
key, | ||
elementId, | ||
needsWorkaround: true, | ||
asyncFnName: asyncFn.name | ||
}); | ||
} | ||
@@ -28,0 +36,0 @@ // See provider `provideInitData()` |
@@ -16,11 +16,12 @@ export { useSuspense }; | ||
}; | ||
declare function useSuspense<T>({ key, elementId, suspenses, resolver, resolverSync, needsWorkaround }: { | ||
declare function useSuspense<T>({ key, elementId, suspenses, resolver, resolverSync, needsWorkaround, asyncFnName }: { | ||
key: string; | ||
elementId: string; | ||
suspenses: Suspenses; | ||
resolver: () => Promise<T>; | ||
resolver: () => T; | ||
resolverSync?: () => null | { | ||
value: T; | ||
value: Awaited<T>; | ||
}; | ||
needsWorkaround?: true; | ||
}): T; | ||
asyncFnName: string; | ||
}): Awaited<T>; |
export { useSuspense }; | ||
import { assert, getGlobalVariable } from './utils'; | ||
import { assert, assertWarning, isPromise, getGlobalVariable } from './utils'; | ||
// Workaround for React useId() bug | ||
@@ -10,3 +10,3 @@ const workaroundCache = getGlobalVariable('workaroundCache', {}); | ||
//*/ | ||
function useSuspense({ key, elementId, suspenses, resolver, resolverSync, needsWorkaround }) { | ||
function useSuspense({ key, elementId, suspenses, resolver, resolverSync, needsWorkaround, asyncFnName }) { | ||
DEBUG && console.log('=== useSuspense()'); | ||
@@ -49,3 +49,3 @@ const suspenseId = getSuspenseId(key, elementId); | ||
{ | ||
const updateSuspense = (s) => { | ||
const updateSuspenseAsync = (s) => { | ||
suspense = s; | ||
@@ -72,10 +72,20 @@ if (!needsWorkaround) { | ||
DEBUG && console.log('resolver()'); | ||
promise.then((value) => { | ||
updateSuspense({ state: 'done', value }); | ||
DEBUG && console.log('=== resolver() done', suspense); | ||
}); | ||
updateSuspense({ state: 'pending', promise }); | ||
if (!isPromise(promise)) { | ||
const fnName = asyncFnName || 'fn'; | ||
assertWarning(false, `[useAsync(key, ${fnName})] You provided a function \`${fnName}\` which didn't return a promise`, { | ||
onlyOnce: true, | ||
showStackTrace: true | ||
}); | ||
suspense = suspenses[suspenseId] = { state: 'done', value: promise }; | ||
} | ||
else { | ||
promise.then((value) => { | ||
updateSuspenseAsync({ state: 'done', value }); | ||
DEBUG && console.log('=== resolver() done', suspense); | ||
}); | ||
updateSuspenseAsync({ state: 'pending', promise }); | ||
} | ||
} | ||
catch (err) { | ||
updateSuspense({ state: 'error', err }); | ||
updateSuspenseAsync({ state: 'error', err }); | ||
} | ||
@@ -82,0 +92,0 @@ assert(suspense); |
export * from '../utils/assert'; | ||
export * from '../utils/getGlobalVariable'; | ||
export * from '../utils/isPromise'; |
export * from '../utils/assert'; | ||
export * from '../utils/getGlobalVariable'; | ||
export * from '../utils/isPromise'; |
@@ -8,3 +8,3 @@ export { assert }; | ||
import { projectInfo } from './projectInfo'; | ||
const errorPrefix = `[${projectInfo.npmPackageName}]`; | ||
const errorPrefix = `[${projectInfo.npmPackageName}@${projectInfo.projectVersion}]`; | ||
const internalErrorPrefix = `${errorPrefix}[Bug]`; | ||
@@ -11,0 +11,0 @@ const usageErrorPrefix = `${errorPrefix}[Wrong Usage]`; |
@@ -1,2 +0,2 @@ | ||
const PROJECT_VERSION = '0.3.0'; | ||
const PROJECT_VERSION = '0.3.1'; | ||
export const projectInfo = { | ||
@@ -3,0 +3,0 @@ projectName: 'react-streaming', |
{ | ||
"name": "react-streaming", | ||
"description": "React 18 Streaming. Full-fledged & Easy.", | ||
"version": "0.3.0", | ||
"version": "0.3.1", | ||
"main": "./dist/cjs/server/hooks.js", | ||
@@ -45,3 +45,3 @@ "peerDependencies": { | ||
"@brillout/part-regex": "^0.1.2", | ||
"@brillout/release-me": "^0.0.6", | ||
"@brillout/release-me": "^0.0.7", | ||
"@types/node": "^15.12.2", | ||
@@ -48,0 +48,0 @@ "@types/react": "^18.0.9", |
@@ -185,13 +185,15 @@ <p align="center"> | ||
async function fetchMovie(id) { | ||
const response = await fetch(`https://star-wars.brillout.com/api/films/${id}.json`) | ||
return response.json() | ||
} | ||
// This component is isomorphic: it works on both the client-side and server-side. | ||
// The data fetched while SSR is automatically passed and re-used on the client for hydration. | ||
function Movie({ id }) { | ||
const movie = useAsync( | ||
async () => { | ||
const response = await fetch(`https://star-wars.brillout.com/api/films/${id}.json`) | ||
return response.json() | ||
}, | ||
'star-wars-movies', // You need to provide a unique key | ||
[id] // Only re-run if `id` changes | ||
) | ||
const key = [ | ||
'star-wars-movies', | ||
id // Re-run `fetchMovie()` if `id` changes | ||
] | ||
const movie = useAsync(key, () => fetchMovie(id)) | ||
return ( | ||
@@ -210,2 +212,4 @@ <ul> | ||
See [`useAsync()` (Library Authors)](#useasync-library-authors) for more information. | ||
<br/> | ||
@@ -227,5 +231,6 @@ | ||
### `useAsync()` (Library Authors) | ||
> This section is a low-level description of `useAsync()`. For a high-levl description, see [`useAsync()`](#useasync) instead. | ||
> This section is a low-level description of `useAsync()`. For a high-level description, see [`useAsync()`](#useasync) instead. | ||
@@ -240,10 +245,5 @@ ```jsx | ||
} | ||
const key = 'some-unique-key' | ||
const deps = ['some-cache-invalidating-values'] | ||
const key = ['some', 'invalidating', 'values'] | ||
// `useAsync()` suspends rendering until the promise returned by `someAsyncFunc()` resolves. | ||
const value = useAsync( | ||
someAsyncFunc, | ||
key, // Required, and should be unique for each component. | ||
deps // Optional: array of values. | ||
) | ||
const value = useAsync(key, someAsyncFunc) | ||
assert(value === 'someData') | ||
@@ -258,7 +258,9 @@ } | ||
If you want to re-run `someAsyncFunc()`, then change `deps`. This is similar to the `deps` argument of React's `useEffect(fn, deps)`. | ||
If you want `someAsyncFunc()` to be re-run, then change `key`. The `someAsyncFunc()` is only re-run if when the component is un-mounted and re-mounted, or if `key` changes. For example, changing the state of your component (e.g. with `useState()`) will *not* re-run `someAsyncFunc()` if you provide the same `key`. | ||
If `<SomeComponent>` is rendered only on the client-side, then `useAsync()` is essentially just a cache. | ||
Usually the key is set to `['name-of-the-function', ...functionArguments]`. | ||
> You can think of `key` to serve a similar purpose to [React Queries's key](https://tanstack.com/query/v4/docs/guides/query-keys), and to the `deps` argument of React's [`useEffect(fn, deps)`](https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects). | ||
### `injectToStream()` | ||
@@ -265,0 +267,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
80572
1648
301
0