기존 fetch useState useEffect
접근 방식을 React-TanStack-Query로 바꾸는 것에 대한 이전 논의를 기억하시나요? QueryProvider
설정, 기본 쿼리 작성, 변형 처리 등 기본 사항을 사용해 왔다면 이미 이점을 경험했을 것입니다. 그러나 우리는 이제 막 그 기능을 탐색하기 시작했습니다.
데이터 가져오기를 크게 향상시켜 애플리케이션 성능을 "좋음"에서 "매우 빠른" 수준으로 변화시키는 고급 기술을 자세히 살펴보겠습니다.
이전 가이드에서는 React-TanStack-Query를 사용한 기본 영화 목록을 보여주었습니다.
<code class="language-javascript">const { data: movies, error, isLoading } = useQuery(['movies'], fetchMovies);</code>
이것은 좋은 출발점이지만 넷플릭스 수준의 반응성을 목표로 한다면 어떨까요? 기술을 한층 더 끌어올리자.
초기 영화 목록에서는 사용자가 클릭한 후 기다려야 했습니다. 이를 대폭 개선할 수 있습니다.
<code class="language-javascript">// components/MovieList.jsx import { useQueryClient } from '@tanstack/react-query'; export default function MovieList() { const queryClient = useQueryClient(); // Leveraging our existing fetchMovies function const prefetchMovie = async (movieId) => { await queryClient.prefetchQuery({ queryKey: ['movie', movieId], queryFn: () => fetchMovieDetails(movieId), // Maintain freshness for 5 minutes staleTime: 5 * 60 * 1000, }); }; return ( <div className="grid grid-cols-4 gap-4"> {movies.map(movie => ( <div key={movie.id} onMouseEnter={() => prefetchMovie(movie.id)} className="movie-card" > {movie.title} </div> ))} </div> ); }</code>
이제 사용자가 영화 위로 마우스를 가져가면 세부정보가 미리 로드되어 클릭 시 즉시 액세스할 수 있습니다! ✨
초기 기사에서는 기본 돌연변이를 다루었습니다. 낙관적인 업데이트로 최적화해 보겠습니다.
<code class="language-javascript">// hooks/useUpdateMovie.js export function useUpdateMovie() { const queryClient = useQueryClient(); return useMutation({ mutationFn: updateMovie, // The key improvement onMutate: async (newMovie) => { // Halt ongoing refetches await queryClient.cancelQueries(['movie', newMovie.id]); // Store current state (for rollback if needed) const previousMovie = queryClient.getQueryData(['movie', newMovie.id]); // Immediate (optimistic) update queryClient.setQueryData(['movie', newMovie.id], newMovie); return { previousMovie }; }, // Error handling onError: (err, newMovie, context) => { queryClient.setQueryData( ['movie', newMovie.id], context.previousMovie ); }, }); }</code>
순차 로딩은 이제 과거의 일입니다.
<code class="language-javascript">// pages/movie/[id].js export default function MoviePage({ movieId }) { const results = useQueries({ queries: [ { queryKey: ['movie', movieId], queryFn: () => fetchMovie(movieId), }, { queryKey: ['cast', movieId], queryFn: () => fetchCast(movieId), }, { queryKey: ['reviews', movieId], queryFn: () => fetchReviews(movieId), }, ], }); if (results.some(result => result.isLoading)) { return <LoadingSpinner />; } const [movie, cast, reviews] = results.map(r => r.data); return <MovieDetails cast={cast} movie={movie} reviews={reviews} />; }</code>
페이지를 매긴 예제를 원활한 무한 스크롤로 업그레이드해 보겠습니다.
<code class="language-javascript">// components/InfiniteMovieList.jsx import { useInfiniteQuery } from '@tanstack/react-query'; import { useInView } from 'react-intersection-observer'; export default function InfiniteMovieList() { const { ref, inView } = useInView(); const { data, fetchNextPage, hasNextPage, isFetchingNextPage, } = useInfiniteQuery({ queryKey: ['movies'], queryFn: fetchMoviePage, getNextPageParam: (lastPage) => lastPage.nextCursor, }); useEffect(() => { if (inView && hasNextPage) { fetchNextPage(); } }, [inView, hasNextPage]); return ( <div> {data.pages.map((page) => ( page.movies.map((movie) => ( <MovieCard key={movie.id} movie={movie} /> )) ))} <div ref={ref}> {isFetchingNextPage ? <LoadingSpinner /> : null} </div> </div> ); }</code>
이것은 첫 번째 기사인 Next.js 14 서버 구성 요소 통합에서 사용할 수 없는 기능입니다.
<code class="language-javascript">const { data: movies, error, isLoading } = useQuery(['movies'], fetchMovies);</code>
<code class="language-javascript">// components/MovieList.jsx import { useQueryClient } from '@tanstack/react-query'; export default function MovieList() { const queryClient = useQueryClient(); // Leveraging our existing fetchMovies function const prefetchMovie = async (movieId) => { await queryClient.prefetchQuery({ queryKey: ['movie', movieId], queryFn: () => fetchMovieDetails(movieId), // Maintain freshness for 5 minutes staleTime: 5 * 60 * 1000, }); }; return ( <div className="grid grid-cols-4 gap-4"> {movies.map(movie => ( <div key={movie.id} onMouseEnter={() => prefetchMovie(movie.id)} className="movie-card" > {movie.title} </div> ))} </div> ); }</code>
<code class="language-javascript">// hooks/useUpdateMovie.js export function useUpdateMovie() { const queryClient = useQueryClient(); return useMutation({ mutationFn: updateMovie, // The key improvement onMutate: async (newMovie) => { // Halt ongoing refetches await queryClient.cancelQueries(['movie', newMovie.id]); // Store current state (for rollback if needed) const previousMovie = queryClient.getQueryData(['movie', newMovie.id]); // Immediate (optimistic) update queryClient.setQueryData(['movie', newMovie.id], newMovie); return { previousMovie }; }, // Error handling onError: (err, newMovie, context) => { queryClient.setQueryData( ['movie', newMovie.id], context.previousMovie ); }, }); }</code>
<code class="language-javascript">// pages/movie/[id].js export default function MoviePage({ movieId }) { const results = useQueries({ queries: [ { queryKey: ['movie', movieId], queryFn: () => fetchMovie(movieId), }, { queryKey: ['cast', movieId], queryFn: () => fetchCast(movieId), }, { queryKey: ['reviews', movieId], queryFn: () => fetchReviews(movieId), }, ], }); if (results.some(result => result.isLoading)) { return <LoadingSpinner />; } const [movie, cast, reviews] = results.map(r => r.data); return <MovieDetails cast={cast} movie={movie} reviews={reviews} />; }</code>
초기 설정보다 훨씬 발전했습니다! 이러한 개선 사항은 정말 뛰어난 사용자 경험을 만드는 데 매우 중요합니다.
모든 것을 한 번에 구현할 필요는 없다는 점을 기억하세요. 기본부터 시작한 다음 필요에 따라 이러한 최적화를 점진적으로 통합하세요.
다음에 누군가가 귀하의 애플리케이션 속도에 대해 언급하면 그것이 왜 그렇게 인상적인지 정확히 알게 될 것입니다. ?
즐거운 코딩하세요! React-TanStack-Query는 무한한 가능성을 제공합니다. 다음에는 무엇을 살펴볼까요?
위 내용은 Next.js에서 React-TanStack-Query를 한 단계 더 발전시키세요의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!