Skip to content

Instantly share code, notes, and snippets.

@DanielHoffmann
Created November 17, 2022 08:46
Show Gist options
  • Select an option

  • Save DanielHoffmann/cccfe75eec6d25b6797fdd8f2830e4cb to your computer and use it in GitHub Desktop.

Select an option

Save DanielHoffmann/cccfe75eec6d25b6797fdd8f2830e4cb to your computer and use it in GitHub Desktop.

Revisions

  1. DanielHoffmann created this gist Nov 17, 2022.
    56 changes: 56 additions & 0 deletions debouncing.tsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,56 @@
    import { Suspense, useEffect, useState } from 'react'
    import { ErrorBoundary } from './components/ErrorBoundary'
    import { Loader } from './components/Loader'

    export function App() {
    const [search, setSearch] = useState<string>('')
    const [debouncedSearch, setDebouncedSearch] = useState<string>('')

    useEffect(() => {
    const timeout = setTimeout(() => {
    setDebouncedSearch(search)
    }, 500)
    return () => {
    clearTimeout(timeout)
    }
    }, [search])

    return (
    <div>
    <input
    onChange={(ev) => {
    setSearch(ev.target.value)
    }}
    type="text"
    value={search}
    />

    <Suspense fallback={<Loader />}>
    <ErrorBoundary fallback={<div>An error occurred</div>}>
    <HideList debouncedSearch={debouncedSearch} search={search}>
    <List search={debouncedSearch} />
    </HideList>
    </ErrorBoundary>
    </Suspense>
    </div>
    )
    }

    function HideList({
    search,
    debouncedSearch,
    children,
    }: {
    search: string
    debouncedSearch: string
    children: React.ReactNode
    }) {
    if (search !== debouncedSearch) {
    // we want to hide <List /> as soon as the user starts typing and show <Loader />
    // this triggers the Suspense tag above it in the tree
    throw new Promise(() => {
    //
    })
    }
    return <>{children}</>
    }