Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Você usa APIs do jeito errado

Hugo
July 16, 2022

Você usa APIs do jeito errado

Uma introdução ao React Query v3

Hugo

July 16, 2022
Tweet

More Decks by Hugo

Other Decks in Programming

Transcript

  1. Você usa APIs do


    jeito errado
    Uma introdução ao React Query

    View Slide

  2. Oi, eu sou o Hugo
    E eu também já usei APIs do jeito errado

    View Slide

  3. Vamos começar um
    projeto novo

    View Slide

  4. View Slide

  5. View Slide

  6. A API da timeline está pronta

    View Slide

  7. A API da timeline está pronta
    Beleza, a gente vai implementar

    View Slide

  8. É 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();


    }, [])

    View Slide

  9. É 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();


    }, [])

    View Slide

  10. É 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();


    }, [])

    View Slide

  11. É 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();


    }, [])

    View Slide

  12. É 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();


    }, [])

    View Slide

  13. 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();


    }, [])

    View Slide

  14. function TimelinePage() {


    const timelineData = useTimelineData();




    if (!timelineData) { return null; }




    return (





    {timelineData.posts.map((post) => (





    ))}





    )


    }

    View Slide

  15. Tá pronto, chefe

    View Slide

  16. Tá pronto, chefe
    Agora a API dos posts está pronta

    View Slide

  17. Tá pronto, chefe
    Agora a API dos posts está pronta
    Beleza, vamos lá. Tá fácil.

    View Slide

  18. View Slide

  19. 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;


    }

    View Slide

  20. 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;


    }

    View Slide

  21. Tá pronto

    View Slide

  22. Tá pronto
    Tá pronto?

    View Slide

  23. Tá pronto
    Tá pronto?
    Alguém consegue me dizer quais são os
    problemas da implementação atual?

    View Slide

  24. Alguém consegue me dizer quais são os
    problemas da implementação atual?

    View Slide

  25. Erros e Exceções

    View Slide

  26. Erros e Exceções

    View Slide

  27. Error
    Erros e Exceções

    View Slide

  28. Batching

    View Slide

  29. 1
    4
    3
    2
    useTimelineData
    Batching

    View Slide

  30. 1
    4
    3
    2
    useTimelineData Batching
    Batching

    View Slide

  31. 1
    4
    3
    2
    useTimelineData Batching
    Batching

    View Slide

  32. Caching

    View Slide

  33. Caching

    View Slide

  34. Caching useTimelineData

    View Slide

  35. Cache Invalidation
    New

    View Slide

  36. Cache Invalidation
    New New

    View Slide

  37. Race Condition

    View Slide

  38. Race Condition
    Busca T
    T
    T
    T
    T
    T

    View Slide

  39. Busca T
    Ty
    Type
    TypeSc
    TypeScri
    TypeScript
    T
    T
    T
    T
    T
    T
    Race Condition

    View Slide

  40. Busca T
    Ty
    Type
    TypeSc
    TypeScri
    TypeScript
    Requisições
    T
    Ty
    Type
    TypeSc
    TypeScri
    TypeScript
    T
    T
    T
    T
    T
    T
    Race Condition

    View Slide

  41. T
    Ty
    Type
    TypeSc
    TypeScri
    TypeScript
    Requisições
    T
    Ty
    Type
    TypeSc
    TypeScri
    TypeScript
    Race Condition Latência
    T
    Ty
    Type
    TypeSc
    TypeScri
    TypeScript

    View Slide

  42. Retries

    View Slide

  43. Retries

    View Slide

  44. 1
    4
    3
    2
    Requisições
    Retries

    View Slide

  45. 1
    4
    3
    2
    Requisições
    1
    4
    3
    2
    Retries

    View Slide

  46. 1
    4
    3
    2
    Requisições
    1
    4
    3
    2
    3
    Retry
    Retry
    Retry
    Sucesso
    Retries
    Retries

    View Slide

  47. Erros e Exceções
    Batching
    Caching
    Cache Invalidation
    Race Condition
    Retries

    View Slide

  48. Erros e Exceções
    Batching
    Caching
    Cache Invalidation
    Race Condition
    Retries
    Cancelamento
    Prefetching
    In
    fi
    nite Pagination
    Polling
    Optimistic Updates
    Refetching
    E muito mais

    View Slide

  49. Ninguém implementa
    tudo isso

    View Slide

  50. Você não quer ter que
    implementar tudo isso

    View Slide

  51. React Query

    View Slide

  52. 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;


    }

    View Slide

  53. async function fetchData() {


    const response = await fetch(`/posts/${id}`);


    const data = await response.json();


    setPostData(data);


    }

    View Slide

  54. async function fetchData() {


    const response = await fetch(`/posts/${id}`);


    const data = await response.json();


    setPostData(data);


    }

    View Slide

  55. async function fetchData() {


    const response = await fetch(`/posts/${id}`);


    return response.json();


    setPostData(data);


    }

    View Slide

  56. function usePostData(id) {


    return useQuery(['posts', id], () => fetchPost(id));


    }

    View Slide

  57. function usePostData(id) {


    return useQuery(['posts', id], () => fetchPost(id));


    }

    View Slide

  58. function usePostData(id) {


    return useQuery(['posts', id], () => fetchPost(id));


    }

    View Slide

  59. function usePostData(id) {


    return useQuery(['posts', id], () => fetchPost(id));


    }

    View Slide

  60. function PostPage({params: {id}}) {


    const {data, isLoading} = usePostData(id);




    if (isLoading) { return null; }




    return (





    )


    }

    View Slide

  61. function PostPage({params: {id}}) {


    const {data, isLoading} = usePostData(id);




    if (isLoading) { return null; }




    return (





    )


    }

    View Slide

  62. function PostPage({params: {id}}) {


    const {data, isLoading} = usePostData(id);




    if (isLoading) { return null; }




    return (





    )


    }

    View Slide

  63. const {


    data,


    isLoading,


    isSuccess,


    error,


    isError,


    refetch,


    /* ... */


    } = usePostData(id);

    View Slide

  64. Erros e Exceções
    Batching
    Caching
    Cache Invalidation
    Race Condition
    Retries
    Cancelamento
    Prefetching
    In
    fi
    nite Pagination
    Polling
    Optimistic Updates
    Refetching
    Sites Robustos

    View Slide

  65. Con
    fi
    gurável

    View Slide

  66. staleTime: 0

    View Slide

  67. staleTime: 0
    ...
    0 ms

    View Slide

  68. cacheTime: 1000 * 60 * 5

    View Slide

  69. retry: 3

    View Slide

  70. refetchOnWindowFocus: true

    View Slide

  71. refetchOnWindowFocus: true
    ... ...

    View Slide

  72. function usePostData(id) {


    return useQuery(['posts', id], () => fetchPost(id), {


    staleTime: 1000 * 20,


    cacheTime: 1000,


    refetchOnWindowsFocus: false,


    });


    }

    View Slide

  73. Mutations

    View Slide

  74. New

    View Slide

  75. New New
    u

    View Slide

  76. New New
    useMutation

    View Slide

  77. 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();


    }

    View Slide

  78. 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 ? () : (





    {/* ... */}





    )


    }

    View Slide

  79. 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 ? () : (





    {/* ... */}





    )


    }

    View Slide

  80. 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 ? () : (





    {/* ... */}





    )


    }

    View Slide

  81. 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 ? () : (





    {/* ... */}





    )


    View Slide

  82. queryClient.invalidateQueries(['posts', id]);


    View Slide

  83. DevTools

    View Slide

  84. DevTools

    View Slide

  85. Hugo, eu parei de prestar atenção
    Já uso o getServerProps
    Não preciso do React Query

    View Slide

  86. Hugo, eu parei de prestar atenção
    Já uso o getServerProps
    Não preciso do React Query
    E se eu te falar que...

    View Slide

  87. E se eu te falar que...
    React Query trabalha com dados assíncronos

    View Slide

  88. E se eu te falar que...
    React Query trabalha com dados assíncronos
    Qualquer dado assíncrono

    View Slide

  89. const [stream, setStream] = useState();


    useEffect(() => {


    async function getMedia() {


    const newStream = await navigator.mediaDevices.getUserMedia({video: true});


    setStream(newStream);


    }




    getMedia();


    }, [])

    View Slide

  90. function useUserMedia() {


    return useQuery(


    ['userMedia'],


    () => navigator.mediaDevices.getUserMedia({video: true})


    );


    }

    View Slide

  91. function useUserMedia() {


    return useQuery(


    ['userMedia'],


    () => navigator.mediaDevices.getUserMedia({video: true}),


    { staleTime: Infinity }


    );


    }

    View Slide

  92. "The best part


    is no part"

    View Slide

  93. View Slide

  94. De nada!

    View Slide

  95. View Slide

  96. View Slide

  97. View Slide