recoil을 사용해서 게시물 리스트를 불러오는 작업도중 에러를 발견하였습니다.
코드를 한번 보면서 생각해보니 뭔가 비동기 처리하는 과정중 에러라고 생각하여 에러내용을 분석하였습니다.
아직 마운트되지 않은 구성 요소에서는 React 상태 업데이트를 수행할 수 없습니다. 이는 나중에 비동기적으로 호출하여 구성 요소를 업데이트하려고 시도하는 렌더링 함수에 부작용이 있음을 나타냅니다. 대신 이 작업을 useEffect로 이동하세요.
관련내용을 검색하여 찾아보니
컴포넌트가 마운트 되기 전에 상태를 불러왔기 때문에 발생한 에러이고
보통의 마운트가 완료된 이후 데이터를 호출하기 위하여 useEffect(() => {} ,[]) 안에 호출 매서드를 넣어주었습니다.
하지만 useRecoilValue 는 react Hook이기 때문에 useEffect의 안에서 사용할 수 없습니다.
async function fetchDataFromFirebase() {
try {
const querySnapshot: QuerySnapshot = await getDocs(
collection(db, 'show'),
)
const data = querySnapshot.docs.map((doc) => {
const postData = doc.data()
const post: Partial<PostState> = {
id: doc.id,
...postData,
}
return post as PostState
})
return data
} catch (error) {
console.error('error', error)
return []
}
}
export const getAllPostSelectors = selector<PostState[]>({
key: 'getAllPostsSelector',
get: async function fetchData() {
const data = await fetchDataFromFirebase()
return data
},
})
<React.Suspense fallback={<div>Loading...</div>}>
컴포넌트가 읽어 들이고 있는 데이터가 아직 준비되지 않았다고 React에 알려주는 일종의 메커니즘입니다.
데이터 불러오기 시작 → 렌더링 시작 → 데이터 불러오기 완료 순서로 동작하는 데이터 호출 로직에서 데이터 호출 완료 여부를 인지하여 데이터 불러오기를 완료할 때까지 fallback 속성 값으로 넣어준 컴포넌트를 표시합니다.
위의 방법과 또 다른 방법이 있을거같아서 찾아보니
recoil 에서 제공하는 useRecoilValueLoadable 과 react 의 useMemo 를 사용해서 렌더링하는 방식이 있었습니다.
export function ShowList() {
const boardList = useRecoilValueLoadable(getAllPostSelectors)
const rows = useMemo(() => {
return boardList?.state === 'hasValue' ? boardList?.contents : []
}, [boardList])
return (
<S.Container>
<Title text={'전체보기'} size="h2" />
<S.PostWrap>
{rows.map((post) => (
<PostItem key={post.id} post={post} />
))}
</S.PostWrap>
</S.Container>
)
}
useRecoilValueLoadable은 Recoil의 훅 중 하나로, Recoil 상태를 읽어오는 동시에 해당 상태의 로딩 상태를 알려줍니다. 이를 통해 비동기적으로 데이터를 가져올 때 로딩 상태를 효과적으로 다룰 수 있습니다.
이외에도 다른속성
useMemo는 React의 훅 중 하나로, 메모이제이션된 값을 반환합니다. 이는 특히 계산 비용이 높은 작업이나 렌더링 성능을 최적화해야 하는 경우 유용합니다.