TypeError: Cannot read property 'map' of undefined
[
[
{
"img" : "imgs/HeeYun/coffee.jpg",
"title" : "커피 1"
},
{
"img" : "imgs/HeeYun/coffee2.jpg",
"title" : "커피 2"
},
{
"img" : "imgs/HeeYun/coffee3.jpg",
"title" : "커피 3"
},
{
"img" : "imgs/HeeYun/coffee4.jpg",
"title" : "커피 4"
}
],
[
{
"img" : "imgs/HeeYun/blackCoffee.jpg",
"title" : "Black Coffee"
},
{
"img" : "imgs/HeeYun/coffee11.jpg",
"title" : "커피 11"
}
]
]
-
위의 코드는 이미지 사진들에 대한 mock data이다.
-
이 mock data는 전체 큰 배열과 내부에 두 개의 배열로 구성되어 있다.
{imgData[0].map((el)=>{
return ( < ImgList coffeeImg={el.img} coffeeName = {el.title}/> );
})}
- 위의 코드에서 map 함수를 통해서 imgData라는 이름을 가진 mock data에서 첫번째 배열을 가져올려고 하는데 제목에서 본 거와 같은 오류가 떴다.
💡 문제 해결 방안
const [imgData, setImgData] = useState([]);
useEffect(() => {
fetch('http://localhost:3000/data/imgData.json', {
method: 'GET'
})
.then(res => res.json())
.then(data => {
setImgData(data);
});
},[])
-
useState를 사용해서 mock data를 불러왔는데, 이 때 setter 함수를 사용했다.
-
setter 함수는 비동기적으로 작동해서 맨 처음 imgData의 초기 값인 빈 배열을 불러온다.
-
리액트에서는 렌더링이 화면에 커밋 된 후에야 모든 효과를 실행한다.
-
React는 return에서 map 함수를 반복실행할 때, 첫번째 시도에 데이터가 아직 안들어와도 렌더링이 실행된다.
아직도 이해 못해서 여전히 생기는 의문점
{imgData.map((el)=>{
return ( < ImgList coffeeImg={el.img} coffeeName = {el.title}/> );
})}
-
바로 위의 코드는 내가 맨 처음 구현한 코드다. 이 때는 맨 위의 mock data처럼 두 개의 배열이 있는게 아니라 하나의 배열만 있었고, 그 때는 동작이 잘됐다.
-
imgData와 imgData[0]의 차이는 setter 함수가 비동기적으로 발생한다는 측면에서 달라지는 문제다.
-
imgData와 imgData[0]의 setter 함수가 공통적으로 맨 처음 가져오는 데이터는 useState안의 imgData state다.
-
imgData.map하면 처음부터 imgData 라는 이름의 mock data 전체를 불러들일 수 있다.
-
하지만 imgData[0].map 하면 처음 imgData mock data를 불러왔을 때는 두 개로 나눠진 배열들을 불러왔을 것 이다. 그래서 map함수는 어떤 걸 동작시킬지 인식을 하지 못해서 발생한 문제다.
마침내 고안한 해결 방안
-
만약 데이터가 아직 안들어오거나 즉시 처리할 수 없다면 && 방식을 사용한다.
-
형식은 { true && expression } 일 때는 항상 expression을 return하고,
{ false && expression } 일 때는 항상 false 값을 가져서 이 때는 무시하고 건너 뛴다.
-
imgData[0]&&imgData[0].map의 경우, 첫번째 시도에서는 imgData[0]이 undefined로 false 값을 가지기 때문에 리액트가 건너 뛰어버린다.
-
그 다음 두번째 시도에서는 이미 setter 함수가 imgData의 state를 업데이트 시켜서 imgData mock data가 두 개의 배열로 나눠진 상태임을 인지한 다음 동작해서 imgData[0]을 인식해서 true 값을 가진다. 이 때 expression이 동작된다.
결론 : &&를 쓰자
const [imgData, setImgData] = useState([]);
useEffect(() => {
fetch('http://localhost:3000/data/imgData.json', {
method: 'GET'
})
.then(res => res.json())
.then(data => {
setImgData(data);
});
},[])
useState를 사용해서 mock data를 불러왔는데, 이 때 setter 함수를 사용했다.
setter 함수는 비동기적으로 작동해서 맨 처음 imgData의 초기 값인 빈 배열을 불러온다.
리액트에서는 렌더링이 화면에 커밋 된 후에야 모든 효과를 실행한다.
React는 return에서 map 함수를 반복실행할 때, 첫번째 시도에 데이터가 아직 안들어와도 렌더링이 실행된다.
{imgData.map((el)=>{
return ( < ImgList coffeeImg={el.img} coffeeName = {el.title}/> );
})}
바로 위의 코드는 내가 맨 처음 구현한 코드다. 이 때는 맨 위의 mock data처럼 두 개의 배열이 있는게 아니라 하나의 배열만 있었고, 그 때는 동작이 잘됐다.
imgData와 imgData[0]의 차이는 setter 함수가 비동기적으로 발생한다는 측면에서 달라지는 문제다.
imgData와 imgData[0]의 setter 함수가 공통적으로 맨 처음 가져오는 데이터는 useState안의 imgData state다.
imgData.map하면 처음부터 imgData 라는 이름의 mock data 전체를 불러들일 수 있다.
하지만 imgData[0].map 하면 처음 imgData mock data를 불러왔을 때는 두 개로 나눠진 배열들을 불러왔을 것 이다. 그래서 map함수는 어떤 걸 동작시킬지 인식을 하지 못해서 발생한 문제다.
만약 데이터가 아직 안들어오거나 즉시 처리할 수 없다면 && 방식을 사용한다.
형식은 { true && expression } 일 때는 항상 expression을 return하고,
{ false && expression } 일 때는 항상 false 값을 가져서 이 때는 무시하고 건너 뛴다.
imgData[0]&&imgData[0].map의 경우, 첫번째 시도에서는 imgData[0]이 undefined로 false 값을 가지기 때문에 리액트가 건너 뛰어버린다.
그 다음 두번째 시도에서는 이미 setter 함수가 imgData의 state를 업데이트 시켜서 imgData mock data가 두 개의 배열로 나눠진 상태임을 인지한 다음 동작해서 imgData[0]을 인식해서 true 값을 가진다. 이 때 expression이 동작된다.
Author And Source
이 문제에 관하여(TypeError: Cannot read property 'map' of undefined), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@432421412/TypeError-Cannot-read-property-map-of-undefined저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)