TypeError: Cannot read property 'map' of undefined

황희윤·2021년 12월 6일
0
[
  [
    {
      "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이 동작된다.

결론 : &&를 쓰자

profile
HeeYun's programming study

0개의 댓글