Recoil selector를 통한 비동기식 데이터 조회
16731 단어 Recoil
비동기 데이터 조회에서 Recoil의 selector를 사용한 상황에서 어떤 동작 실험을 진행합니까?
또한 코드는 여기서 동작을 확인할 수 있다
https://codesandbox.io/s/ecstatic-austin-k2c3z
응용 프로그램 설명
이른바 키워드 검색에 이름을 표시하는 프로그램만 있으면 된다.데이터가 네트워크를 통해 키워드 검색을 할 수 있도록 상상하십시오. (실제로는 로컬에서만 선별하고wait에서만 진행됩니다.)
검색 결과를 비동기적으로 불러오는 동안loading indicator가 검색 결과에 겹쳐집니다.
코드 해설
atom/selector의 정의
/**
* states
*/
const keywordInputState = atom({
key: "keywordInput",
default: ""
});
const keywordState = atom({
key: "keyword",
default: ""
});
const searchResultState = selector({
key: "searchResult",
async get({ get }) {
const keyword = get(keywordState);
const results = await searchEntries(keyword);
return results;
}
});
키워드를 표시하는 입력의tom(keywordInputState
과 확정된 키워드를 표시하는tomkeywordState
, 키워드 검색 결과를 표시하는selectorsearchResultState
를 준비합니다.searchResultState
확정된 키워드를 이용하여 비동기 호출searchEntries()
을 호출하여 그 결과를 되돌려주는 selector가 된다.어셈블리 정의
키워드 입력 및 검색 프로세서
function KeywordSearchForm() {
const [keywordInput, setKeywordInput] = useRecoilState(keywordInputState);
const onSearch = useRecoilCallback(async ({ getPromise, set }) => {
const keyword = await getPromise(keywordInputState);
set(keywordState, keyword);
}, []);
return (
<div className="search-form">
<input
type="text"
value={keywordInput}
onChange={e => setKeywordInput(e.target.value)}
onKeyDown={e => (e.keyCode === 13 ? onSearch() : null)}
/>
<button onClick={onSearch}>Search</button>
</div>
);
}
keywordInputState
참조useRecoilState
를 통해 키워드의 입력 상태를 제어합니다.물론 이렇게useState
도 되고, 그렇다면 uncontrolled도 되고, 어쨌든.Enter 키를 누를 때 Search 버튼을 누를 때onSearch()
프로세서가 작동합니다.onSearch()
에서 keywordInputState
의 값만 읽고 키워드 확인keywordState
으로 설정합니다.검색 결과 표시
function SearchResult() {
const searchResultLoadable = useRecoilValueReplayLoadable(searchResultState);
const searchResult = searchResultLoadable.getLastResolvedValue();
return (
<div className="result">
{searchResult ? (
<ul className="list">
{searchResult.map(item => (
<li>{item.name}</li>
))}
</ul>
) : (
undefined
)}
{searchResultLoadable.state === "loading" ? (
<div className="loading">
<span>loading...</span>
</div>
) : (
undefined
)}
{searchResultLoadable.state === "hasError" ? (
<div className="error">{searchResultLoadable.contents.message}</div>
) : (
undefined
)}
</div>
);
}
검색 결과는 참조searchResultState
의 훅스를 이용한다.비동기 마운트 상태를 확인하기 위해 대상을 가져옵니다 Loadable
.물론 useRecoilValue
에서 직접 값을 얻을 수도 있지만 이 경우<Suspense>
는 포위되어야 한다.또 직접 사용
useRecoilValueLoadable
이 아니라 후술처럼 이용useRecoilValueReplayLoadable
의 사용자 정의 갈고리를 사용했다.전체 애플리케이션
export default function App() {
return (
<div className="App">
<KeywordSearchForm />
<SearchResult />
</div>
);
}
사용자 지정 바닥글리코일의 경우 비동기 처리에서
<Suspense>
로 구성 요소를 둘러싸고 대체 내용을 표시할 수 있지만 같은 구성 요소의 지난번 결과를 직접 표시하기는 어렵다.또 정부useRecoilStateLoadable
에서 비동기 전의 해결치를 직접 얻을 수 없다.따라서 최종 해결 값Loadable
을 얻기 위해 대상에 사용getLastResolvedValue()
방법의 사용자 정의 연결을 준비했다.import { useRef, useEffect } from "react";
import { useRecoilValueLoadable, Loadable, RecoilValue } from "recoil";
type ReplayLoadable<T> = Loadable<T> & {
getLastResolvedValue(): T | undefined;
};
export function useRecoilValueReplayLoadable<T>(
state: RecoilValue<T>
): ReplayLoadable<T> {
const loadable = useRecoilValueLoadable(state);
const lastValueRef = useRef<T>();
useEffect(() => {
if (loadable.state === "hasValue") {
lastValueRef.current = loadable.contents;
}
}, [loadable]);
return {
...loadable,
getLastResolvedValue() {
return this.state === "hasValue" ? this.contents : lastValueRef.current;
}
};
}
여기서는 Conceurent ModeuseTransition
를 사용하면 원활하게 사용할 수 있습니다.실험
캐시 정보
상기 프로그램의 키워드를 바꾸어 검색해 보십시오.
searchEntries()
1sec 정도의wait를 강제로 사용하지만 서로 다른 키워드로 검색한 후 같은 키워드로 한 번 검색하면 검색 결과를 즉시 되돌려줍니다.이로써 비동기적인 selector라도 계산 결과는 캐시된다는 것을 알 수 있다.또한state 이전의 값에 의존할 뿐만 아니라 모든 변화가 가능합니다state 값의 결과는 memo의 것임을 알 수 있다.
비동기 오류 정보
실제로
searchEntries()
는 1/10의 확률로 오류를 되돌려준다(네트워크 오류 등을 가정한다).이것은 무작위로 같은 키워드로 검색하면 오류가 발생하지 않을 수 있지만 잘못된 같은 키워드로 다시 검색하면 무조건 실시간 오류가 발생할 수 있다.이로써 비동기 처리에서 발생하는 오류도 캐시된다는 것을 알 수 있다.현재queryversion과 같은tom을 준비하여 캐시를 강제로 무효화(실제로는 memoization 키만 변경)하는 의존성 사전 제작
searchResultState
selector를 준비할 필요가 있다.
Reference
이 문제에 관하여(Recoil selector를 통한 비동기식 데이터 조회), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/stomita/items/6e82481957e499a3d85a텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)