FrontEnd/React.js
[React.js]Recoil selector 비동기 처리 에러
푸고배
2022. 1. 13. 20:14
Error: App suspended while rendering, but no fallback UI was specified. Add a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.
const [data, setData] = useRecoilState(exRecoilSelecter);
위와 같이 미리 선언된 selector를 사용하기 위해서 useRecoilValue를 통해 접근할 시, 해당 에러가 발생한다.
비동기 처리 시(loading, 랜더링할 데이터가 도착하기 이전) 보여줄 fallback UI가 없다는 에러메시지이다.
해결 방법은 아래와 같다.
1. i18n.js 구성 변경(react-i18next 사용 중인 경우)
i18n
.use(XHR)
.use(LanguageDetector)
.init({
react: {
useSuspense: false // <---- this will do the magic
}
});
2. React.Suspense 사용
import React,{ Suspense } from 'react';
import { ExComponent } from '../components';
const App = () => {
return(
<RootRecoil>
<Suspense fallback={<div>Loading...</div>}>
<ExComponent />
</Suspense>
</RootRecoil>
);
}
export default App;
3. Recoil의 Ladable 사용
Suspense 대신 Recoil의 Loadable을 사용할 수도 있다.
function UserInfo({userID}) {
const userNameLoadable = useRecoilValueLoadable(userNameQuery(userID));
switch (userNameLoadable.state) {
case 'hasValue':
return <div>{userNameLoadable.contents}</div>;
case 'loading':
return <div>Loading...</div>;
case 'hasError':
throw userNameLoadable.contents;
}
}
Lodable은 atom이나 selector의 현재 상태를 나타내는 객체이며, 아래와 같은 인터페이스를 가진다.
- state : atom 혹은 selector의 최신 상태, 'hasValue', 'hasError', 'loading'의 값을 가질 수 있다.
- contents : Loadable에 의해서 대표되는 값, state에 따라 아래와 같은 값을 가진다.
- hasValue : 실제 값을 가진다.
- hasError: Error 객체를 가진다.
- loading : toPromise()를 사용해 값의 Promise를 얻을 수 있다.
import { useMemo } from 'react';
import { getExDataSelector } from './atoms';
import { useRecoilValueLoadable } from 'recoil';
function App() {
const dataLoadable = useRecoilValueLoadable(getTokenSelector);
const data = useMemo(() => {
return dataLoadable?.state === 'hasValue' ? dataLoadable.contents : null;
});
}
export default App;
dataLoadable의 state가 loading이 완료된 'hasValue' 시점이 아닌 경우 null로 초기화를 해주는 코드를 통해서 해당 에러를 해결할 수 있다.
Reference
반응형