Skip to content

Instantly share code, notes, and snippets.

@drcmda
Created May 8, 2023 10:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save drcmda/b261f485e0ad7e8de881b8a7b597f6be to your computer and use it in GitHub Desktop.
Save drcmda/b261f485e0ad7e8de881b8a7b597f6be to your computer and use it in GitHub Desktop.
import { Suspense, createContext, useTransition, useState, useContext, useMemo } from 'react'
import debounce from 'lodash/debounce'
const pendingContext = createContext()
export function Pending({ fallback, debounce, children }) {
return (
<Suspense fallback={fallback}>
<PendingChildren debounce={debounce}>{children}</PendingChildren>
</Suspense>
)
}
function PendingChildren({ children, debounce = 100 }) {
const [pending, start] = useTransition()
const api = useMemo(() => [pending, start, debounce], [pending, start, debounce])
return <pendingContext.Provider value={api}>{children}</pendingContext.Provider>
}
export function usePendingState(initialState, customDelay) {
const [, start, delay] = useContext(pendingContext)
const [value, setValue] = useState(initialState)
const [set] = useState(() => debounce(value => start(() => setValue(value)), customDelay ?? delay))
return [value, set]
}
export function usePending() {
return useContext(pendingContext)[0]
}
@drcmda
Copy link
Author

drcmda commented May 8, 2023

<Pending fallback={null>
  <Foo />
</Pending>

function Foo() {
  const [foo, setFoo] usePendingState(0)
  const [bar, setBar] usePendingState(1)
  // If anything is pending
  const pending = usePending()
  // Suspend if foo or bar change
  const result = suspend(someRemoteTask, [foo, bar])
  return (
    <div style={{ color: pending ? "red" : "green" }}>{result}</div>
  )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment