import { For, createSignal } from 'solid-js'
import { render } from 'solid-js/web'
import { createAsyncThrottler } from '@tanstack/solid-pacer/async-throttler'
interface SearchResult {
id: number
title: string
}
const fakeApi = async (term: string): Promise<Array<SearchResult>> => {
await new Promise((resolve) => setTimeout(resolve, 500))
return [
{ id: 1, title: `${term} result ${Math.floor(Math.random() * 100)}` },
{ id: 2, title: `${term} result ${Math.floor(Math.random() * 100)}` },
{ id: 3, title: `${term} result ${Math.floor(Math.random() * 100)}` },
]
}
function App() {
const [searchTerm, setSearchTerm] = createSignal('')
const [results, setResults] = createSignal<Array<SearchResult>>([])
const [error, setError] = createSignal<Error | null>(null)
const handleSearch = async (term: string) => {
if (!term) {
setResults([])
return
}
const data = await fakeApi(term)
setResults(data)
setError(null)
return data
}
const setSearchAsyncThrottler = createAsyncThrottler(
handleSearch,
{
wait: 1000,
onError: (error) => {
console.error('Search failed:', error)
setError(error as Error)
setResults([])
},
},
)
const handleSearchThrottled = setSearchAsyncThrottler.maybeExecute
async function onSearchChange(e: Event) {
const newTerm = (e.target as HTMLInputElement).value
setSearchTerm(newTerm)
const results = await handleSearchThrottled(newTerm)
console.log('results', results)
}
return (
<div>
<h1>TanStack Pacer createAsyncThrottler Example</h1>
<div>
<input
autofocus
type="search"
value={searchTerm()}
onInput={onSearchChange}
placeholder="Type to search..."
style={{ width: '100%' }}
autocomplete="new-password"
/>
</div>
{error() && <div>Error: {error()?.message}</div>}
<div>
<setSearchAsyncThrottler.Subscribe
selector={(state) => ({
successCount: state.successCount,
isPending: state.isPending,
isExecuting: state.isExecuting,
})}
>
{(state) => (
<>
<p>API calls made: {state().successCount}</p>
<For each={results()}>{(item) => <li>{item.title}</li>}</For>
{state().isPending ? (
<p>Pending...</p>
) : state().isExecuting ? (
<p>Executing...</p>
) : null}
</>
)}
</setSearchAsyncThrottler.Subscribe>
</div>
<setSearchAsyncThrottler.Subscribe selector={(state) => state}>
{(state) => (
<pre style={{ 'margin-top': '20px' }}>
{JSON.stringify(state(), null, 2)}
</pre>
)}
</setSearchAsyncThrottler.Subscribe>
</div>
)
}
render(() => <App />, document.getElementById('root')!)