React 공식 홈페이지 따라하기
React 공식 홈페이지 따라하기 - Effect가 필요하지 않을 수도 있다!?(3)
vitamin3000
2024. 12. 9. 23:11
데이터 가져오기
많은 앱이 데이터 가져오기를 시작하기 위해 Effect를 사용한다.
아래와 같은 데이터를 가져오는 Effect를 작성하는 것은 매우 일반적이다.
function SearchResults({ query }) {
const [results, setResults] = useState([]);
const [page, setPage] = useState(1);
useEffect(() => {
// 🔴 피하세요: 정리 로직 없이 가져오기
fetchResults(query, page).then(json => {
setResults(json);
});
}, [query, page]);
function handleNextPageClick() {
setPage(page + 1);
}
// ...
}
데이터 가져오기를 이벤트 핸들러로 옮길 필요는 없다.
하지만. hello를 입력한다고 했을 때 h he hel 이 아닌 h hel he로 응답을 받을 수도 있는 것이다.
이것을 "경쟁 조건"이라 하는데, 서로 다른 두 요청이 서로 "경쟁"하여 예상과 다른 순서로 도착하는 것을 말한다.
경쟁 조건을 수정하려면 오래된 응답을 무시하는 정리 함수를 추가해야한다.
function SearchResults({ query }) {
const [results, setResults] = useState([]);
const [page, setPage] = useState(1);
useEffect(() => {
let ignore = false;
fetchResults(query, page).then(json => {
if (!ignore) {
setResults(json);
}
});
return () => {
ignore = true;
};
}, [query, page]);
function handleNextPageClick() {
setPage(page + 1);
}
// ...
}
이렇게 작성하면 Effect가 데이터를 가져올 때 마지막으로 요청된 응답을 제외한 모든 응답이 무시된다.
데이터 가져오기를 구현할 때 다음의 조건들도 고려해봐야한다.
- 경쟁 조건 처리
- 응답 캐싱(사용자가 뒤로가기 버튼을 클릭하여 이전 화면을 즉시 볼 수 있도록)
- 서버에서 데이터를 가져오는 방법(초기 서버 렌더링 HTML에 스피너 대신 가져온 콘텐츠가 포함되도록)
- 네트워크 워터풀을 피하는 방법(자식이 모든 부모를 기다리지 않고 데이터를 가져올 수 있도록)
이러한 문제는 React뿐만 아니라 모든UI라이브러리에 적용된다
따라서 모던 프레임워크는 Effect에서 데이터를 가져오는 것보다 더 효율적인 내장 데이터 가져오기 매커니즘을 제공한다.
const results = useData(`/api/search?${params}`);
- 전체 컴포넌트 트리의 state를 초기화하려면 다른 key를 전달
- 컴포넌트가 표시되어 실행되는 코드는 Effect에 있어야하고 나머지는 이벤트에 있어야 한다.