구조는 다음과 같다
HomeContainer.js
GuestHome.js
, OwnerHome.js
HomeContainer.js에서 두 자식 컴포넌트 중 어떤 컴포넌트를 렌더링 할 지 결정한다.
각 자식 컴포넌트는 렌더링 시에 서버에 정보를 요청해야 하는데, 각각 다른 API로 요청을 해야했다.
방식: 각 자식 컴포넌트의 useEffect() 안에 서버에 정보를 요청하는 코드를 넣었다.
문제: 자식 컴포넌트의 useEffect()가 동작하지 않음.
// HomeContainer.js
function HomeContainer () {
const [showGuest, setShowGuest] = useState(false);
const [showOwner, setShowOwner] = useState(false);
(생략) GuestHome, OwnerHome 중에 어떤 컴포넌트를 렌더링할 지 결정하는 로직
return (
{showGuest && <GuestHome/>}
{showOwner && <OwnerHome/>}
)
}
showGuest, showOwner라는 상태가 업데이트 됐을 때 컴포넌트가 렌더링 되면서 각 컴포넌트의 useEffect가 동작할 거라고 생각했는데, 아무리 해도 상태 업데이트 타이밍에 맞춰서 useEffect 동작이 안됐다.
How to use useEffect() inside a child component to fetch data?
이 글이 날 구원했어
자식컴포넌트에 복잡한 로직 넣지 않기
자식 컴포넌트에 있는 서버 요청 코드를 부모 컴포넌트로 옮겼더니 바로 문제 해결됐다
// HomeContainer.js
const [showGuest, setShowGuest] = useState(false);
useEffect(() => {
if (showGuest){
서버에 데이터를 요청하는 dispatch
}
},[showGuest])
...
return (
{showGuest && <GuestHome/>}
)
// GuestHome.js
HomeContainer에서 보낸 dispatch를 통해 store에 저장해둔 데이터를 불러와서 보여주는 역할만!
즉, 프레젠테이셔널 컴포넌트로만 작동하게끔.
정확히 왜 안됐는지는 모르겠지만 무튼 부모-자식 컴포넌트가 존재할 때, 특히 부모 컴포넌트의 상태값에 따라 자식 컴포넌트를 조건부 렌더링 하는 경우에는 자식 컴포넌트 안의 useEffect()가 동작을 안한다. 그러니 자식 컴포넌트가 아닌 부모 컴포넌트에서 해당 작업을 진행할 것!
문제: 위 코드의 useEffect가 HomeContainer.js
첫 렌더링 시에만 실행되고, showGuest 상태가 업데이트 됐을 때는 실행되지 않음. => 즉, 서버에 요청이 안감... 😹
useEffect 다루기 너무 어렵다.
그러다가 문득 왜 dispatch를 useEffect 내에서 보냈지 하는 의문이 들어서 코드를 수정했다.
const data = location.state;
if (typeof data !== "undefined") {
if (data.from == "frontdoor" && data.status == 1) {
dispatch(getGuestInfo(match.params.id)).then((response) => {
// Guest임이 확인된 경우 바로 dispatch
if (response.type == "guest_info_success") {
setShowGuest(true);
}
});
} else if (data.from == "frontdoor" && data.status == 0) {
// owner임이 확인된 경우 바로 dispatch
dispatch(getOwnerInfo(match.params.id)).then((response) => {
if (response.type == "owner_info_success") {
setShowOwner(true);
}
});
} else if (data.from == "register") {
dispatch(getOwnerInfo(match.params.id)).then((response) => {
if (response.type == "owner_info_success") {
setShowOwner(true);
}
});
}
} else {
(생략)
}
}, []);
showGuest가 true로 바뀌면 서버에 요청을 전송하는 코드를 다른 useEffect에 넣는 게 아니라, 그냥 guest, owner 를 판단하는 useEffect에 넣어줬다.
같은 코드만 하루종일 쳐다보고 있으니까 내 생각에 갇혔었다. 몇 시간 쉬다가 다시 보니 이렇게 간단한 해결책이!
HomeContainer.js
렌더링 시 useEffect 실행GuestHome.js
OwnerHome.js
중 하나가 렌더링된다.GuestHome.js
OwnerHome.js
는 각기 상응하는 store에서 정보를 가져와 화면에 보여준다.그래도 그냥 혼자 프로젝트 했으면 마주치지도 못했을 문제점을 발견하고, 혼자 끙끙대며 해결해본 과정이 너무 재밌었다 희희 물론 다 해결 됐으니까 재밌다고 할 수 있는 것임.
바쁘더라도 종종 기록해야지!
프레젠테이셔널 컴포넌트가 단순히 데이터를 받아서 보여주는 역할을 한다는 사실만 기억하셨으면 시간을 아끼실 수 있었을텐데 아쉬워요
그래도 시행착오 공유해주셔서 감사합니다!