안녕하세요 여러분!
저는 React 쿼리의 일부 필수 기능(가져오기, 캐싱, 재시도 등)을 모방하지만 더 컴팩트한 useAsync라는 경량 React 후크를 작업해 왔습니다. 쉽게 사용자 정의 가능한 패키지. 다음은 관련 코드 섹션을 참조하여 내부적으로 작동하는 방식에 대한 간략한 분석입니다. 전체 코드를 보려면 다음 저장소로 이동하세요.
GitHub의 전체 소스 코드.
후크는 npm에서 api-refetch로 사용할 수도 있습니다.
React Query와 SWR은 모두 훌륭한 라이브러리이지만 몇 가지 이유로 좀 더 실용적인 접근 방식을 원했습니다.
가벼운 설치 공간
React Query와 SWR은 기능이 풍부하지만 상대적으로 크기가 클 수 있습니다(React Query ~2.2MB, SWR ~620kB). api-refetch는 약 250kB이므로 번들 크기가 큰 관심사인 소형 앱에 이상적입니다. 이 후크는 다른 라이브러리(Intlayer)의 종속성으로 설치되도록 되어 있습니다. 결과적으로 솔루션의 크기가 중요한 고려 사항이었습니다.
손쉬운 맞춤화 및 최적화
로컬 저장소에서 데이터 저장/가져오기, 간단한 접근 방식을 사용한 병렬 요청 관리
와 같은 몇 가지 구체적인 기능이 필요했습니다.
프로젝트에 직접 저장소를 복제하거나 코드를 복사하면 원치 않는 기능을 제거하고 필요한 기능만 유지할 수 있습니다. 이는 번들 크기를 줄일 뿐만 아니라 불필요한 재렌더링 및 증가를 최소화하여 특정 요구 사항에 맞는 더 간결하고 성능이 뛰어난 솔루션을 제공합니다.
필수 제공자 없음
후크를 전역으로 만들고 사용법을 최대한 단순하게 유지하기 위해 컨텍스트 제공자를 피하고 싶었습니다. 그래서 Zustand 매장을 기반으로 Hooke 버전을 만들었습니다(아래 예시 참조).
학습 연습
처음부터 비동기 라이브러리를 구축하는 것은 동시성, 캐싱 및 상태 관리 내부를 이해하는 훌륭한 방법입니다.
간단히 말해서, 라이브러리를 작고 이해하기 쉽게 유지하면서 나에게 필요한 기능을 정확하게 파악하고 필요하지 않은 기능은 건너뛸 수 있는 기회였습니다.
React 후크 관리:
다음은 api-refetch의 핵심 사항과 useAsync.tsx의 코드 관련 부분에 대한 간략한 참조입니다.
// This map stores any in-progress Promise to avoid sending parallel requests // for the same resource across multiple components. const pendingPromises = new Map(); const fetch: T = async (...args) => { // Check if a request with the same key + args is already running if (pendingPromises.has(keyWithArgs)) { return pendingPromises.get(keyWithArgs); } // Otherwise, store a new Promise and execute const promise = (async () => { setQueryState(keyWithArgs, { isLoading: true }); // ...perform fetch here... })(); // Keep it in the map until it resolves or rejects pendingPromises.set(keyWithArgs, promise); return await promise; };
// Handle periodic revalidation if caching is enabled useEffect( () => { if (!revalidationEnabled || revalidateTime <= 0) return; // Revalidation is disabled if (!isEnabled || !enabled) return; // Hook is disabled if (isLoading) return; // Fetch is already in progress if (!isSuccess || !fetchedDateTime) return; // Should retry either of revalidate if (!(cacheEnabled || storeEnabled)) return; // Useless to revalidate if caching is disabled const timeout = setTimeout(() => { fetch(...storedArgsRef.current); }, revalidateTime); return () => clearTimeout(timeout); }, [ /* dependencies */ ] );
useEffect( () => { const isRetryEnabled = errorCount > 0 && retryLimit > 0; const isRetryLimitReached = errorCount > retryLimit; if (!isEnabled || !enabled) return; // Hook is disabled if (!isRetryEnabled) return; // Retry is disabled if (isRetryLimitReached) return; // Retry limit has been reached if (!(cacheEnabled || storeEnabled)) return; // Useless to retry if caching is disabled if (isLoading) return; // Fetch is already in progress if (isSuccess) return; // Hook has already fetched successfully const timeout = setTimeout(() => { fetch(...storedArgsRef.current); }, retryTime); return () => clearTimeout(timeout); }, [ /* dependencies */ ] );
// Auto-fetch data on hook mount if autoFetch is true useEffect( () => { if (!autoFetch) return; // Auto-fetch is disabled if (!isEnabled || !enabled) return; // Hook is disabled if (isFetched && !isInvalidated) return; // Hook have already fetched or invalidated if (isLoading) return; // Fetch is already in progress fetch(...storedArgsRef.current); }, [ /* dependencies */ ] );
여기에서 로컬 저장소 논리, 쿼리 무효화 등이 포함된 전체 코드를 확인하세요.
관심이 있으시면 자유롭게 사용해 보고, 문제를 보고하고, 참여해 보세요. 어떤 피드백이라도 감사히 받겠습니다!
코드를 복사하거나 (repo)[https://github.com/aymericzip/api-refetch]를 코드하세요
또는
// This map stores any in-progress Promise to avoid sending parallel requests // for the same resource across multiple components. const pendingPromises = new Map(); const fetch: T = async (...args) => { // Check if a request with the same key + args is already running if (pendingPromises.has(keyWithArgs)) { return pendingPromises.get(keyWithArgs); } // Otherwise, store a new Promise and execute const promise = (async () => { setQueryState(keyWithArgs, { isLoading: true }); // ...perform fetch here... })(); // Keep it in the map until it resolves or rejects pendingPromises.set(keyWithArgs, promise); return await promise; };
// Handle periodic revalidation if caching is enabled useEffect( () => { if (!revalidationEnabled || revalidateTime <= 0) return; // Revalidation is disabled if (!isEnabled || !enabled) return; // Hook is disabled if (isLoading) return; // Fetch is already in progress if (!isSuccess || !fetchedDateTime) return; // Should retry either of revalidate if (!(cacheEnabled || storeEnabled)) return; // Useless to revalidate if caching is disabled const timeout = setTimeout(() => { fetch(...storedArgsRef.current); }, revalidateTime); return () => clearTimeout(timeout); }, [ /* dependencies */ ] );
그렇습니다! 한 번 해보고 어떻게 되는지 알려주세요. GitHub에서는 피드백, 질문 또는 기여를 환영합니다.
GitHub: api-refetch
즐거운 코딩하세요!
위 내용은 React의 비동기 데이터 가져오기 및 캐싱을 위한 경량 후크 쇼케이스의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!