Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Você usa APIs do jeito errado
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Hugo
July 16, 2022
Programming
81
0
Share
Você usa APIs do jeito errado
Uma introdução ao React Query v3
Hugo
July 16, 2022
More Decks by Hugo
See All by Hugo
ReferenceError: talk is not defined
hugooliveirad
1
54
Três hábitos para escrever CSS escalável
hugooliveirad
0
680
Three habits to write scalable CSS
hugooliveirad
0
73
Mantendo webapps em produção, sem dor de cabeça
hugooliveirad
1
280
Minha webapp está em produção, e agora?
hugooliveirad
0
53
Other Decks in Programming
See All in Programming
柔軟なPDFレイアウトエディタを支える型システム設計 — Discriminated UnionとConditional Typeの実践
minako__ph
4
1.4k
作って学ぶ、 JSX (TSX) ランタイムの基本
syumai
7
1.5k
AIエージェントと協働するCLI開発 — BunとOpenClawで学んだこと
yoshikouki
1
240
不変条件と整合性境界—ビジネスが決める設計判断と実現パターン / Invariants and Consistency Boundaries
nrslib
13
3.4k
Stage 3 Decorators でできること / できないこと / TSKaigi 2026
susisu
1
1.5k
技術記事、AIに書かせるか、自分で書くか? 〜それでも私が自分の手で書く理由〜 / #QiitaConference
jnchito
2
1.3k
「エンジニアインターン、どうやって取った?」準備のリアルを語るLT会 Progate BAR
akiomatic
0
120
関係性から理解する"同一性"の型用語たち
pvcresin
2
640
dRuby over BLE
makicamel
2
310
権限チェックの一貫性を型で守る TypeScript による多層防御
mnch
4
1.1k
Old Dog, New Tricks: The Java 25 Reinvention - JNation
bazlur_rahman
0
140
oxlintはeslint/typescript-eslintを置き換えられるのか
shomafujita
2
320
Featured
See All Featured
How to build a perfect <img>
jonoalderson
1
5.6k
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.5k
Odyssey Design
rkendrick25
PRO
2
690
GraphQLとの向き合い方2022年版
quramy
50
15k
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.5k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
220
Paper Plane
katiecoart
PRO
1
51k
The Pragmatic Product Professional
lauravandoore
37
7.3k
How Software Deployment tools have changed in the past 20 years
geshan
0
34k
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
2
390
AI: The stuff that nobody shows you
jnunemaker
PRO
8
690
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
200
Transcript
Você usa APIs do jeito errado Uma introdução ao React
Query
Oi, eu sou o Hugo E eu também já usei
APIs do jeito errado
Vamos começar um projeto novo
None
None
A API da timeline está pronta
A API da timeline está pronta Beleza, a gente vai
implementar
É só substituir os valores do JSON pela API const
[timelineData, setTimelineData] = useState(); useEffect(() => { async function fetchData() { const response = await fetch('/timeline'); const data = await response.json(); setTimelineData(data); } fetchData(); }, [])
É só substituir os valores do JSON pela API const
[timelineData, setTimelineData] = useState(); useEffect(() => { async function fetchData() { const response = await fetch('/timeline'); const data = await response.json(); setTimelineData(data); } fetchData(); }, [])
É só substituir os valores do JSON pela API const
[timelineData, setTimelineData] = useState(); useEffect(() => { async function fetchData() { const response = await fetch('/timeline'); const data = await response.json(); setTimelineData(data); } fetchData(); }, [])
É só substituir os valores do JSON pela API const
[timelineData, setTimelineData] = useState(); useEffect(() => { async function fetchData() { const response = await fetch('/timeline'); const data = await response.json(); setTimelineData(data); } fetchData(); }, [])
É só substituir os valores do JSON pela API const
[timelineData, setTimelineData] = useState(); useEffect(() => { async function fetchData() { const response = await fetch('/timeline'); const data = await response.json(); setTimelineData(data); } fetchData(); }, [])
function useTimelineData() { } É só substituir os valores do
JSON pela API const [timelineData, setTimelineData] = useState(); useEffect(() => { async function fetchData() { const response = await fetch('/timeline'); const data = await response.json(); setTimelineData(data); } fetchData(); }, [])
function TimelinePage() { const timelineData = useTimelineData(); if (!timelineData) {
return null; } return ( <Timeline> {timelineData.posts.map((post) => ( <Post key={post.id} post={post} /> ))} </Timeline> ) }
Tá pronto, chefe
Tá pronto, chefe Agora a API dos posts está pronta
Tá pronto, chefe Agora a API dos posts está pronta
Beleza, vamos lá. Tá fácil.
None
function usePostData(id) { const [postData, setPostData] = useState(); useEffect(() =>
{ async function fetchData() { const response = await fetch(`/posts/${id}`); const data = await response.json(); setPostData(data); } fetchData(); }, [id]) return postData; }
function usePostData(id) { const [postData, setPostData] = useState(); useEffect(() =>
{ async function fetchData() { const response = await fetch(`/posts/${id}`); const data = await response.json(); setPostData(data); } fetchData(); }, [id]) return postData; }
Tá pronto
Tá pronto Tá pronto?
Tá pronto Tá pronto? Alguém consegue me dizer quais são
os problemas da implementação atual?
Alguém consegue me dizer quais são os problemas da implementação
atual?
Erros e Exceções
Erros e Exceções
Error Erros e Exceções
Batching
1 4 3 2 useTimelineData Batching
1 4 3 2 useTimelineData Batching Batching
1 4 3 2 useTimelineData Batching Batching
Caching
Caching
Caching useTimelineData
Cache Invalidation New
Cache Invalidation New New
Race Condition
Race Condition Busca T T T T T T
Busca T Ty Type TypeSc TypeScri TypeScript T T T
T T T Race Condition
Busca T Ty Type TypeSc TypeScri TypeScript Requisições T Ty
Type TypeSc TypeScri TypeScript T T T T T T Race Condition
T Ty Type TypeSc TypeScri TypeScript Requisições T Ty Type
TypeSc TypeScri TypeScript Race Condition Latência T Ty Type TypeSc TypeScri TypeScript
Retries
Retries
1 4 3 2 Requisições Retries
1 4 3 2 Requisições 1 4 3 2 Retries
1 4 3 2 Requisições 1 4 3 2 3
Retry Retry Retry Sucesso Retries Retries
Erros e Exceções Batching Caching Cache Invalidation Race Condition Retries
Erros e Exceções Batching Caching Cache Invalidation Race Condition Retries
Cancelamento Prefetching In fi nite Pagination Polling Optimistic Updates Refetching E muito mais
Ninguém implementa tudo isso
Você não quer ter que implementar tudo isso
React Query
function usePostData(id) { const [postData, setPostData] = useState(); useEffect(() =>
{ async function fetchData() { const response = await fetch(`/posts/${id}`); const data = await response.json(); setPostData(data); } fetchData(); }, [id]) return postData; }
async function fetchData() { const response = await fetch(`/posts/${id}`); const
data = await response.json(); setPostData(data); }
async function fetchData() { const response = await fetch(`/posts/${id}`); const
data = await response.json(); setPostData(data); }
async function fetchData() { const response = await fetch(`/posts/${id}`); return
response.json(); setPostData(data); }
function usePostData(id) { return useQuery(['posts', id], () => fetchPost(id)); }
function usePostData(id) { return useQuery(['posts', id], () => fetchPost(id)); }
function usePostData(id) { return useQuery(['posts', id], () => fetchPost(id)); }
function usePostData(id) { return useQuery(['posts', id], () => fetchPost(id)); }
function PostPage({params: {id}}) { const {data, isLoading} = usePostData(id); if
(isLoading) { return null; } return ( <Post post={data.post} /> ) }
function PostPage({params: {id}}) { const {data, isLoading} = usePostData(id); if
(isLoading) { return null; } return ( <Post post={data.post} /> ) }
function PostPage({params: {id}}) { const {data, isLoading} = usePostData(id); if
(isLoading) { return null; } return ( <Post post={data.post} /> ) }
const { data, isLoading, isSuccess, error, isError, refetch, /* ...
*/ } = usePostData(id);
Erros e Exceções Batching Caching Cache Invalidation Race Condition Retries
Cancelamento Prefetching In fi nite Pagination Polling Optimistic Updates Refetching Sites Robustos
Con fi gurável
staleTime: 0
staleTime: 0 ... 0 ms
cacheTime: 1000 * 60 * 5
retry: 3
refetchOnWindowFocus: true
refetchOnWindowFocus: true ... ...
function usePostData(id) { return useQuery(['posts', id], () => fetchPost(id), {
staleTime: 1000 * 20, cacheTime: 1000, refetchOnWindowsFocus: false, }); }
Mutations
New
New New u
New New useMutation
async function createPost(post) { const response = await fetch('/posts', {
method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify(post) }); return response.json(); }
function CreatePostPage() { const mutation = useMutation(createPost); const handleSubmit =
useCallback((event) => { event.preventDefault(); const data = new FormData(event.target); const post = Object.fromEntries(data.entries()); mutation.mutate(post); }, [mutation]); return mutation.isLoading ? (<Spinner />) : ( <form onSubmit={handleSubmit}> {/* ... */} </form> ) }
function CreatePostPage() { const mutation = useMutation(createPost); const handleSubmit =
useCallback((event) => { event.preventDefault(); const data = new FormData(event.target); const post = Object.fromEntries(data.entries()); mutation.mutate(post); }, [mutation]); return mutation.isLoading ? (<Spinner />) : ( <form onSubmit={handleSubmit}> {/* ... */} </form> ) }
function CreatePostPage() { const mutation = useMutation(createPost); const handleSubmit =
useCallback((event) => { event.preventDefault(); const data = new FormData(event.target); const post = Object.fromEntries(data.entries()); mutation.mutate(post); }, [mutation]); return mutation.isLoading ? (<Spinner />) : ( <form onSubmit={handleSubmit}> {/* ... */} </form> ) }
function CreatePostPage() { const mutation = useMutation(createPost); const queryClient =
useQueryClient(); const handleSubmit = useCallback((event) => { event.preventDefault(); const data = new FormData(event.target); const post = Object.fromEntries(data.entries()); mutation.mutate(post, { onSuccess: () => { queryClient.invalidateQueries('timeline'); } }); }, [mutation]); return mutation.isLoading ? (<Spinner />) : ( <form onSubmit={handleSubmit}> {/* ... */} </form> )
queryClient.invalidateQueries(['posts', id]);
DevTools
DevTools
Hugo, eu parei de prestar atenção Já uso o getServerProps
Não preciso do React Query
Hugo, eu parei de prestar atenção Já uso o getServerProps
Não preciso do React Query E se eu te falar que...
E se eu te falar que... React Query trabalha com
dados assíncronos
E se eu te falar que... React Query trabalha com
dados assíncronos Qualquer dado assíncrono
const [stream, setStream] = useState(); useEffect(() => { async function
getMedia() { const newStream = await navigator.mediaDevices.getUserMedia({video: true}); setStream(newStream); } getMedia(); }, [])
function useUserMedia() { return useQuery( ['userMedia'], () => navigator.mediaDevices.getUserMedia({video: true})
); }
function useUserMedia() { return useQuery( ['userMedia'], () => navigator.mediaDevices.getUserMedia({video: true}),
{ staleTime: Infinity } ); }
"The best part is no part"
None
De nada!
None
None
None