Closed hmlinnie closed 3 years ago
좋은 질문입니다! 제가 알려드렸어야 했을 거 같네요 😅
잘 구현하셨습니다.
세미나 2 강의 자료 및 리액트 공식문서 useEffect 에 따르면, useEffect
는 한 번 렌더가 된 다음 실행됩니다. 따라서 axios를 이용한 fetch가 마무리되기 전까지 무조건 한 틱 이상의 간극이 존재하고, 그 기간 동안은 initialData
를 이용해 render하게 됩니다.
굳이 그거 때문이 아니더라도, 생각해보면 서버에서 데이터를 받아올 때까지 시간이 필요합니다. (세미나용 서버 같은 경우에는 워낙 트래픽도 적고 디비도 작아서 그런지 엄청 빠르더라고요. 그래서 잘 안 느껴지셨을 거예요) 보통 비동기 처리에 0.1초 이상이 소요됩니다. 따라서 자연히 그 기간동안은 데이터가 없는 게 맞고, 아무튼 로드가 되기 전까지 initialData
를 써서 render하는 게 맞습니다.
그럼 데이터가 없을 땐 어떻게 하느냐? 데이터가 없는 (아마도 로드되기 전) state에서의 뷰를 만들어 주는 게 일반적입니다. 가령 아래와 같은 방법이 있을 것 같네요!
const [studentList, setStudentList] = useState();
useEffect(() => {
axios.get('/student')
.then(response => {
setStudentList(response.data);
});
}, []);
if (studentList === undefined) return <h1>loading...</h1>
return <StudentListView studentList={studentList} />;
근데 이제 UX를 생각하면 위 같은 방법은 데이터가 로드되기 전까지 아무것도 안 보여주겠다는 건데 좀 별로입니다. 렌더할 때 조건부 렌더링을 써서, studentList === undefined
라면 studentList.map(student => <li> 어쩌구
대신 loading
이라는 텍스트를 띄우거나, 이런 로더 gif를 띄우는 게 베스트겠네요!
사실 저기서 조금만 더 생각하면, studentList === undefined
로 로딩중인 걸 체크하는 건 의미상 그렇게 좋지 않다는 걸 알 수 있습니다. 로딩 끝났는데 토큰이 만료돼서 axios.get
이 에러나서 studentList === undefined
가 유지되는 중일 수도 있잖아요?
그런 부분을 고려한다면, 보통 isLoading
이라는 state를 하나 더 두는 방식을 채택합니다. axios.get
호출하기 전에 true로 설정하고, .then
에서 false로 설정하는 거죠
const [isLoading, setIsLoading] = useState(false);
const [studentList, setStudentList] = useState();
useEffect(() => {
setIsLoading(true);
axios.get('/student')
.then(response => {
setStudentList(response.data);
setIsLoading(false);
});
.catch(err => {
// toast 등으로 에러 보여주고
setIsLoading(false);
})
}, []);
if (isLoading) return <h1>loading...</h1>
return <StudentListView studentList={studentList} />;
또 더 정확한 핸들을 하고 싶다면 에러 발생 시 에러가 발생했다는 걸 보여주기 위해 isLoading
옆에 isError
라는 state도 추가해서 비슷하게 처리할 수도 있겠습니다만 사실 이번 과제 스펙이랑은 관련이 없기도 하고, 여기서 오류가 날 만한 부분이 토큰 만료밖에 없으니 이번 과제에서는 이 api에서 에러가 났을 경우 바로 로그아웃시켜버리는 방식이 좀더 적합할 것 같네요
질문과 관련은 없지만 https://github.com/wafflestudio/19.5-rookies/issues/531 참고하셔서 localStorage 말고 state에서 토큰 가져오도록 변경하시는 걸 추천드립니다!
네!! 알려주신대로 잘 해결했습니다. 자세히 설명해주셔서 감사합니다!!
요약
안녕하세요. 와플 루키 김혜민입니다. 마운트될 때
Useeffect()
를 이용해 데이터를 받아 state에 저장하려 시도하고 있으나 오류가 생겨 질문 드립니다.상황
문제 내용
위 코드와 같이
setStudent
로 데이터를 저장하고, 이후student
객체를 사용하고자 하였으나, student 객체에는 아무것도 저장되지 않았다는 오류 메시지가 계속해서 발생합니다.그래서 여러 가지를 시도하던 중,
const [student, setStudent] = useState()
부분에서useState()
에initialState
를 설정해놓을 경우(가령 더미데이터 저장) 제대로 작동하는 것을 발견했습니다.왜 이런 현상이 발생하는지, 제대로 작동되기 위해 어떤 부분을 고쳐야하는지 궁금합니다!