use-suspensible
v0.2.3
Published
A React hook that can make any data suspensible.
Downloads
2
Readme
use-suspensible
React hooks that can make any data suspensible.
Why?
This is a proof-of-concept for using Suspense with non-promise based async libraries. Also see observable-hooks on implementing Render-as-You-Fetch pattern with Suspense and Rxjs Observable.
Installation
yarn
yarn add use-suspensible
npm
npm install --save use-suspensible
Usage
import React, { Suspense, useState, useEffect } from 'react'
import { useSuspensible } from 'use-suspensible'
function fetchData() {
return new Promise(resolve => {
setTimeout(() => {
resolve({ content: "content" })
}, 3000)
})
}
const App = () => {
const [data, setData] = useState()
useEffect(
() => {
fetchData().then(setData)
},
[]
)
return (
<Suspense fallback={<h1>Loading...</h1>}>
<Content data={data} />
</Suspense>
)
}
function Content({ data }) {
useSuspensible(data)
return (
<h1>{data.content}</h1>
);
}
Default trigger Suspense on null
or undefined
.
useSuspensible(data)
Custom comparison for checking finish state.
useSuspensible(data, data => data.status === 'finish')
You can have any number of useSuspensible
in a Component.
useSuspensible(data1)
useSuspensible(data2)
useSuspensible(data3, data => data.status === 'finish')
return (
<>
<h1>{data1.content}</h1>
<h1>{data2.content}</h1>
<h1>{data3.content}</h1>
</>
)
TypeScript >= 3.7
interface StatePending {
status: 'pending'
value: null
}
interface StateFinish {
status: 'finish'
value: number
}
type States = StatePending | StateFinish
//....
useSuspensible(
data,
(data: States): data is StateFinish => data.status === 'finish'
)
// Now data is of `StateFinish` type.
Beware
Due to the design of Suspense, each time a suspender is thrown, the children of Suspense
Component will be destroyed and reloaded. Do not initialize async data and trigger Suspense in the same Component.
import React, { Suspense, useState, useEffect } from 'react'
import { useSuspensible } from 'use-suspensible'
function fetchData() {
return new Promise(resolve => {
setTimeout(() => {
resolve({ content: "content" })
}, 3000)
})
}
const App = () => {
return (
<Suspense fallback={<h1>Loading...</h1>}>
<Content />
</Suspense>
)
}
function Content({ data }) {
const [data, setData] = useState()
// This will cause infinite update.
useEffect(
() => {
fetchData().then(setData)
},
[]
)
useSuspensible(data)
return (
<h1>{data.content}</h1>
);
}