해당 포스트는 제로베이스 오프라인스쿨 진행 과정 중 React PairProgramming과제를 진행하며 회고를 정리하는 글이다.
Fetching Data
현상
1) useEffect로 감싸지 않고 컴포넌트 내부에서 data fetching을 할 때
Data fetching하는 과정에서 state를 업데이트하면 리 렌더링이 발생하고, 컴포넌트가 리렌더링되면서 data fetcing이 다시 진행되며 무한 루프가 발생함.

2) Lazy initial state
// Lazy initial state
const [state, setState] = useState(() => {
const initialState = someExpensiveComputation(props);
return initialState;
});
// Lazy initial state
// Bad Example
const [tabs, setTabs] = React.useState(() => {
setIsLoading(true);
fetchTabData()
.then((data) => setTabs(data))
.catch((e) => setError(e))
.finally(() => setIsLoading(false));
});
동작은 하지만 `useState` 내부에서 `setter`함수를 사용 하고 있기 때문에 안티 패턴이다.
발견
useEffect의 내부에서 setTabs를 사용하면 처음 렌더링 이후 한번만 data fetching을 수행하게 함.
배운점
비동기 처리를 할 때는 보통 useEffect를 사용한다.
선언
useEffect를 써야 할 때를 명확히 구분하여 적용을 해야겠다.
2. Error Boundary, Suspense
현상
아래는 v1의 useTabs에서 반환한 isLoading과 error 값을 가지고 조건부 렌더링한 코드
const App = () => {
const { tabsData, isLoading, error } = useTabs();
return error ? (
<Error error={error} />
) : isLoading ? (
<Loader isLoading={isLoading} />
) : (
<>
<Title />
<Tabs tabsData={tabsData} />
</>
);
};
발견
ErrorBoundary와 Suspense를 사용한 코드
const App = () => (
<>
<ErrorBoundary fallback={<Error />}>
<Suspense fallback={<Loader />}>
<TabsContainer />
</Suspense>
</ErrorBoundary>
</>
);
배운점
ErrorBoundary와 Suspense를 사용하지 않았을 경우 비동기처리를 하는 컴포넌트마다 각각 isLoading과 error를 처리해줘야 해서 번거롭고 이는 컴포넌트 내부에서 주요한 로직과 상관 없을 수 있다. 하지만 ErrorBoundary와 Suspense를 사용하여 App에서 모든 컴포넌트를 감싸면 한 번에 isLoading과 Error를 처리할 수 있고 코드도 간결해진다.
선언
ErrorBoundary와 Suspense를 적극 사용해야겠다. 또 필요에 따라 적절하게 사용하는 방법을 공부해야겠다.