import { ErrorBoundary, For, Suspense, createSignal } from 'solid-js'
import { A } from '@solidjs/router'
import { noop, useQuery, useQueryClient } from '@tanstack/solid-query'
import type { Character } from '~/services/characters/types'
import { charactersQueries } from '~/services/characters/queries'
function CharacterItem(props: {
char: Character
onSelect: (id: number) => void
}) {
const queryClient = useQueryClient()
const characterQuery = useQuery(() => ({
...charactersQueries.detail(props.char.id),
enabled: false,
}))
const prefetch = () => {
queryClient
.query({
...charactersQueries.detail(props.char.id),
staleTime: 10 * 1000, // only prefetch if older than 10 seconds
})
.catch(noop)
}
return (
<li onMouseEnter={prefetch} onFocusIn={prefetch}>
<button
type="button"
style={characterQuery.isSuccess ? { 'font-weight': 'bold' } : {}}
onClick={() => {
props.onSelect(props.char.id)
}}
>
{props.char.id} - {props.char.name}
</button>{' '}
<A href={`/character/${props.char.id}`}>details</A>
</li>
)
}
function SelectedCharacter(props: { id: number }) {
const characterQuery = useQuery(() => ({
...charactersQueries.detail(props.id),
throwOnError: true,
}))
return <pre>{JSON.stringify(characterQuery.data, null, 2)}</pre>
}
export default function Example() {
const [selectedChar, setSelectedChar] = createSignal(1)
const charactersQuery = useQuery(() => ({
...charactersQueries.list(),
throwOnError: true,
}))
return (
<div class="App">
<p>
Hovering over a character will prefetch it, and when it's been
prefetched it will turn <strong>bold</strong>. Clicking on a prefetched
character will show their stats below immediately, and opening its
details page will render it without a loading state.
</p>
<h2>Characters</h2>
<ErrorBoundary fallback={(error) => <span>Error: {error.message}</span>}>
<Suspense fallback="Loading...">
<ul>
<For each={charactersQuery.data?.results}>
{(char) => (
<CharacterItem char={char} onSelect={setSelectedChar} />
)}
</For>
</ul>
<h3>Selected Character</h3>
<Suspense fallback="Loading...">
<SelectedCharacter id={selectedChar()} />
</Suspense>
</Suspense>
</ErrorBoundary>
</div>
)
}