사건의 발단
데이터를 받아와 useState를 사용해서 화면에 뿌려주고 싶었다.
그리고 내가 받아올 데이터는 [배열] 이었다. (사실 이 기본을 생각하면 틀릴것도 없는 문제인데..)
function Searched() {
const [searched, setSearched] = useState('')
const params = useParams();
const getSearched = async(name)=>{
const data = await fetch(`https://api.spoonacular.com/recipes/complexSearch?apiKey=${process.env.REACT_APP_API_KEY}&query=${name}&number=9`);
const recipes = await data.json();
setSearched(recipes.results)
console.log(recipes.results);
};
useEffect(()=>{
getSearched(params.input)
},[params.input])
return (
<Grid>
{searched.map((recipe)=>{
return(
<div key={recipe.id}>
<img src={recipe.image} alt={recipe.title} />
<h4>{recipe.title}</h4>
</div>
)
})}
</Grid>
)
}
export default Searched
결과는?
searched.map이 function이 아니라고 나오면 1차적으로는 아 내가 배열이 아닌거에 map을 돌렸나? 라고 생각해야하는데 그 생각을 미처 못한 나는 계속 페이지.jsx에 컴포넌트를 잘 넣은건 맞는지, 라우터는 잘 들어갔는지를 전전하며 시간을 허비했다...
그리고 발견한,
const [searched, setSearched] = useState('')
처음에 useState값을 '빈 배열'이 아닌 null로 넣어준 게 눈에 보였고 그 순간 아..! 했다.
빈 배열로 바꿔주니 제대로 동작하는 것을 보고 안심하긴 했지만 '아니 초기값으로 뭘 해놨던지간에 나는 배열데이터를 받아서 map을 돌려준건데 왜 문제가 되지?'라고 생각했는데, 다시 React flow를 천천히 생각해보니 이해가 되었다.
그래서 지금 어떻게 돌아가고있는거냐면...
화면이 처음 마운트 될 때! 즉 다시말해 맨~ 처음 이 화면이 렌더링 될 때에는 아래와 같은 순서로 진행된다.
function Searched() {
// 1. 초기화작업이 진행된다. useState는 ''로 셋팅된다.
const [searched, setSearched] = useState('')
const params = useParams();
// 얘는 함수선언이니까 무시
const getSearched = async(name)=>{
const data = await fetch(`https://api.spoonacular.com/recipes/complexSearch?apiKey=${process.env.REACT_APP_API_KEY}&query=${name}&number=9`);
const recipes = await data.json();
setSearched(recipes.results)
console.log(recipes.results);
};
// 이 useEffect는 렌더링이 끝난 이후에 실행된다!!!
useEffect(()=>{
getSearched(params.input)
},[params.input])
// 2. 리턴문까지 렌더링이 된다.
return (
<Grid>
// 3. 근데 지금 초기화값은 ''인데 map을 돌렸네? -> 오류!!!
{searched.map((recipe)=>{
return(
<div key={recipe.id}>
<img src={recipe.image} alt={recipe.title} />
<h4>{recipe.title}</h4>
</div>
)
})}
</Grid>
)
}
export default Searched
리액트에서 useEffect는 랜더링이 다 진행된 후에 실행된다!
고로 리턴문까지 다 돌고난 그제서야 useEffect는 실행이 될 수 있는데, 그때의 useState는 아직 null이기 때문에 map을 붙여놓은게 당연히 오류를 뿜는것임!
마운트시 실행순서
- Run lazy initializers
- render
- React updates DOM
- Run LayoutEffects
- Browser apints screen
- Run Effects -> 가장 마지막이다.
업데이트시 실행순서
- render -> 초기화과정이 빠졌다.
- React updates DOM
- Cleanup LayoutEffects
- Run LayoutEffects
- Browser apints screen
- Cleanup Effects
- Run Effects -> 역시나 마지막이다.
리액트는 플로우를 잘 이해하고 있지 않으면 불행하다^^
작은 실수에서 큰 깨달음을 얻는다.
리액트를 사용하면서 Hook Flow를 이해하고있지 않으면 읭? 하는 상황이 올 때마다 해결방법을 도무지 찾기가 어려워지니
계속해서 원리를 새기며 코딩하자.
'Front-End Developer > React' 카테고리의 다른 글
이젠, Nav바 만들때 NavLink를 쓰자 - active일 때 CSS스타일링하기 (0) | 2022.07.24 |
---|---|
No routes matched location "/" 오류 간단해결방법(반전의 실수..) (0) | 2022.07.10 |
styled-components 사용시 Invalid hook call 오류 해결하기 (2) | 2022.07.03 |
리액트 유치원이 개원했습니다. (유투브 채널개설) (0) | 2022.06.20 |
useState Lazy initialization - 게으른 초기화가 대체 뭔소리야? (+유투브 영상 업로드) (4) | 2022.06.16 |