React Native를 이용해서 수강신청 연습 앱을 만들던 중, 문제가 발생했다.
로그인 화면에서 빠르게 메뉴 화면으로 넘어가는 경우,
헤더를 제외한 나머지 부분이 렌더링이 되지 않는 것이다. 😣
근데 열 받는 점은 로그인 화면에서 약 10초 기다린 후 페이지 이동 시에는 정상적으로 떴다...
문제 원인은 Recoil의 default값을 AsyncStorage에서 냅다 가져왔기 때문이었다.
AsyncStorage는 말 그대로 비동기적(Async)으로 동작하는데,
데이터를 가져오기도 전에 cartState를 사용하는 페이지(메뉴 화면)으로 이동했기 때문이다.
문제의 코드는 다음과 같다.
export const cartState = atom({
key: 'cartState',
default: storeData(newCart), // : AsyncStorage에 data를 저장하는 함수
});
Recoil Atom Effects의 setSelf()를 이용해서 해결해주었다.
Recoil 공식 문서에서 알려준 방법이다.
지속되는 데이터를 비동기적으로 불러와야 할 때는, setSelf() 함수 내에서 Promise 를 사용하거나 데이터를 비동기적으로 호출할 수 있습니다
export const cartState = atom({
key: 'cartState',
default: [],
effects: [
async ({setSelf, onSet}) => {
setSelf(await getData());
onSet(newCart => {
storeData(newCart);
});
},
],
});
추가로 onSet()을 이용하여 새로운 cartState가 set될 때마다 그 값을 AsyncStorage에 저장해주는 코드도 추가했다.
다음과 같은 코드를 통해 State와 AsyncStorage의 데이터를 동기화할 수 있다.