snapshot of https://github.com/TanStack/query.git (main, 2026-09-16; blobs > 131072B omitted)
Some checks failed
autofix.ci / autofix (push) Failing after 4s
Release / Release (push) Has been skipped
GitHub Actions Security Analysis / Run zizmor (push) Failing after 2s

This commit is contained in:
upstream-mirror
2026-09-16 01:13:08 +05:00
commit 3a013ccdfe
3570 changed files with 490194 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
import { BrowserRouter as Router } from 'react-router-dom'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import Layout from './Layout'
import './styles.css'
const queryClient = new QueryClient()
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<Router>
<Layout />
<ReactQueryDevtools initialIsOpen />
</Router>
</QueryClientProvider>
)
}

View File

@@ -0,0 +1,82 @@
import { useParams, Link as RouterLink } from 'react-router-dom'
import { useQuery } from '@tanstack/react-query'
import { getCharacter, getFilm, getPlanet } from './api'
export default function Character() {
let params = useParams()
const characterId = params.characterId!
const { status, data } = useQuery({
queryKey: ['character', characterId],
queryFn: () => getCharacter(characterId),
})
if (status === 'pending') return <p>Loading...</p>
if (status === 'error') return <p>Error :(</p>
const homeworldUrlParts = data.homeworld.split('/').filter(Boolean)
const homeworldId = homeworldUrlParts[homeworldUrlParts.length - 1]
return (
<div>
<h2 className="text-4xl">{data.name}</h2>
<p>
<strong>Born</strong>: {data.birth_year}
</p>
<p>
<strong>Eyes</strong>: {data.eye_color}
</p>
<p>
<strong>Hair</strong>: {data.hair_color}
</p>
<p>
<strong>Height</strong>: {data.height}
</p>
<p>
<strong>Mass</strong>: {data.mass}
</p>
<p>
<strong>Homeworld</strong>: <Homeworld homeworldId={homeworldId} />
</p>
<h4 className="text-2xl pt-4">Films</h4>
{data.films.map((film: any) => {
const filmUrlParts = film.split('/').filter(Boolean)
const filmId = filmUrlParts[filmUrlParts.length - 1]
return <Film filmId={filmId} key={`${filmId}`} />
})}
</div>
)
}
function Film({ filmId }: { filmId: string }) {
const { data, status } = useQuery({
queryKey: ['film', filmId],
queryFn: () => getFilm(filmId),
})
if (status === 'success') {
return (
<RouterLink
className="text-blue-500 hover:underline"
to={`/films/${filmId}`}
>
<h6 className="text-lg">
{data.episode_id}. {data.title}
</h6>
</RouterLink>
)
}
}
function Homeworld({ homeworldId }: { homeworldId: string }) {
const { data, status } = useQuery({
queryKey: ['homeworld', homeworldId],
queryFn: () => getPlanet(homeworldId),
})
if (status === 'pending') return <span>Loading...</span>
if (status === 'error') return <span>Error :(</span>
return <span>{data.name}</span>
}

View File

@@ -0,0 +1,33 @@
import { Link as RouterLink } from 'react-router-dom'
import { useQuery } from '@tanstack/react-query'
import { getCharacters } from './api'
export default function Characters() {
const { status, data } = useQuery({
queryKey: ['characters'],
queryFn: () => getCharacters(),
})
if (status === 'pending') return <p>Loading...</p>
if (status === 'error') return <p>Error :(</p>
return (
<div>
<h2 className="text-4xl">Characters</h2>
{data.results.map((person: any) => {
const personUrlParts = person.url.split('/').filter(Boolean)
const personId = personUrlParts[personUrlParts.length - 1]
return (
<article key={personId}>
<RouterLink
className="text-blue-500 hover:underline"
to={`/characters/${personId}`}
>
<h6 className="text-xl">{person.name}</h6>
</RouterLink>
</article>
)
})}
</div>
)
}

View File

@@ -0,0 +1,54 @@
import { useParams, Link as RouterLink } from 'react-router-dom'
import { useQuery } from '@tanstack/react-query'
import { getFilm, getCharacter } from './api'
export default function Film() {
const { filmId } = useParams()
if (!filmId) {
return <p>Invalid film ID</p>
}
const { data, status } = useQuery({
queryKey: ['film', filmId],
queryFn: () => getFilm(filmId),
})
if (status === 'pending') return <p>Loading...</p>
if (status === 'error') return <p>Error :(</p>
return (
<div>
<h2 className="text-4xl">{data.title}</h2>
<p>{data.opening_crawl}</p>
<br />
<h4 className="text-2xl">Characters</h4>
{data.characters.map((character: string) => {
const characterUrlParts = character.split('/').filter(Boolean)
const characterId = characterUrlParts[characterUrlParts.length - 1]
return <Character characterId={characterId} key={characterId} />
})}
</div>
)
}
function Character({ characterId }: { characterId: string }) {
const { data, status } = useQuery({
queryKey: ['character', characterId],
queryFn: () => getCharacter(characterId),
})
if (status !== 'success') {
return null
}
return (
<RouterLink
className="text-blue-500 hover:underline"
to={`/characters/${characterId}`}
>
<h6 className="text-lg">{data.name}</h6>
</RouterLink>
)
}

View File

@@ -0,0 +1,42 @@
import { Link as RouterLink } from 'react-router-dom'
import { useQuery } from '@tanstack/react-query'
import { getFilms } from './api'
export default function Films() {
const { data, status } = useQuery({
queryKey: ['films'],
queryFn: () => getFilms(),
})
if (status === 'pending') {
return <p>Loading...</p>
}
if (status === 'error') {
return <p>Error :(</p>
}
return (
<div>
<h2 className="text-4xl">Films</h2>
{data.results.map((film: any) => {
const filmUrlParts = film.url.split('/').filter(Boolean)
const filmId = filmUrlParts[filmUrlParts.length - 1]
return (
<article key={filmId}>
<RouterLink
className="text-blue-500 hover:underline"
to={`/films/${filmId}`}
>
<h6 className="text-xl">
{film.episode_id}. {film.title}{' '}
<em>
({new Date(Date.parse(film.release_date)).getFullYear()})
</em>
</h6>
</RouterLink>
</article>
)
})}
</div>
)
}

View File

@@ -0,0 +1,46 @@
import { Link as RouterLink } from 'react-router-dom'
export default function Home() {
return (
<div>
<h2 className="text-4xl">TanStack Query Demo</h2>
<p>Using the Star Wars API</p>
<p>
(Built by{' '}
<a
className="text-blue-500 hover:underline"
href="https://twitter.com/Brent_m_Clark"
>
@Brent_m_Clark
</a>
)
</p>
<h5 className="text-2xl pt-4">Why TanStack Query?</h5>
<p>
In this demo you will be able to see how TanStack Query is a significant
improvement over <strong>redux</strong>, <strong>mobx</strong>, and any
other general-purpose state container.
</p>
<p>
No reducers, thunks, or sagas. No ES6 models to maintain in order to tag
them as observable.
</p>
<p>
Simply associate a key with your fetch call and let{' '}
<strong>TanStack Query</strong> handle the rest.
</p>
<h5 className="text-2xl pt-4">Ready to get started?</h5>
<p>
Check out the{' '}
<RouterLink className="text-blue-500 hover:underline" to="/films">
Films
</RouterLink>{' '}
and{' '}
<RouterLink className="text-blue-500 hover:underline" to="/characters">
Characters
</RouterLink>
!
</p>
</div>
)
}

View File

@@ -0,0 +1,37 @@
import { Route, Link as RouterLink, Routes } from 'react-router-dom'
import Films from './Films'
import Film from './Film'
import Characters from './Characters'
import Character from './Character'
import Home from './Home'
export default function Layout() {
return (
<div>
<nav className="bg-gray-300 w-full flex flex-row gap-6 justify-center items-center h-12">
<RouterLink to="/">
<span className="uppercase hover:underline">Home</span>
</RouterLink>
<RouterLink to="/films">
<span className="uppercase hover:underline">Films</span>
</RouterLink>
<RouterLink to="/characters">
<span className="uppercase hover:underline">Characters</span>
</RouterLink>
</nav>
<div className="p-2">
<Routes>
<Route exact path="/films" element={<Films />} />
<Route exact path="/films/:filmId" element={<Film />} />
<Route exact path="/characters" element={<Characters />} />
<Route
exact
path="/characters/:characterId"
element={<Character />}
/>
<Route path="/" element={<Home />} />
</Routes>
</div>
</div>
)
}

View File

@@ -0,0 +1,24 @@
export const getFilms = async () => {
const res = await fetch('https://swapi.dev/api/films/')
return await res.json()
}
export const getFilm = async (filmId: string) => {
const res = await fetch(`https://swapi.dev/api/films/${filmId}/`)
return await res.json()
}
export const getCharacters = async () => {
const res = await fetch('https://swapi.dev/api/people/')
return await res.json()
}
export const getCharacter = async (characterId: string) => {
const res = await fetch(`https://swapi.dev/api/people/${characterId}/`)
return await res.json()
}
export const getPlanet = async (planetId: string) => {
const res = await fetch(`https://swapi.dev/api/planets/${planetId}/`)
return await res.json()
}

View File

@@ -0,0 +1,6 @@
import ReactDOM from 'react-dom/client'
import App from './App'
const rootElement = document.getElementById('root')
if (!rootElement) throw new Error('Missing #root element')
ReactDOM.createRoot(rootElement).render(<App />)

View File

@@ -0,0 +1,27 @@
@import 'tailwindcss';
@theme {
--font-sans:
Roboto, BlinkMacSystemFont, -apple-system, Segoe UI, Roboto, Oxygen, Ubuntu,
Cantarell, Fira Sans, Droid Sans, Helvetica Neue, Helvetica, Arial,
sans-serif;
--font-mono:
Roboto Mono, BlinkMacSystemFont, -apple-system, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, Helvetica, Arial,
sans-serif;
}
@layer base {
body {
@apply font-sans;
}
h1,
h2,
h3,
h4,
h5,
h6 {
@apply font-mono;
}
}