위코드에서 공부하며 정리한 내용입니다.
useEffect 로 불러온 목데이터로 map 함수를 돌릴 때 위와 같은 오류가 난다면 아래 내용을 참고하세요.
위 메시지는 map 메소드로 읽어야 할 데이터의 정보가 undefiend 이기 때문에 오류가 나는 것입니다. 아래와 같이 콘솔을 찍어보면,
useEffect(() => {
fetch('/data/productInfo.json')
.then(res => res.json())
.then(res => setProducts(res));
}, []);
console.log(products);
두번째로 불러오는 데이터만 확인하고 넘어가지 않고 첫번째 값으로 undefined 가 나오는 것에 주목해야 합니다. 그 이유를 아래처럼 콘솔을 찍어서 확인 할 수 있습니다. 처음부터 useEffect 가 바로 실행되지 않고 useEffect 없이 1차 렌더 이후 useEffect 가 실행된 것을 확인할 수 있습니다.
useEffect(() => {
console.log('useEffect!');
fetch('/data/productInfo.json')
.then(res => res.json())
.then(res => setProducts(res));
}, []);
console.log('render!');
그래서 이를 해결하는 여러가지 방법을 알아보면, useEffect 로 받아오는 데이터가 undefined 가 아닐때 실행하게 하거나,
{products !== undefined &&
products.map(product => {
return (
<li className="cardBox" key={product.id}>
product 값 자체가 있으면 true 이므로 아래 처럼 쓰거나
{products &&
products.map(product => {
return (
<li className="cardBox" key={product.id}>
옵셔널 체이닝(?.) 문법을 사용할 수 있습니다.
하지만 이런 조건들은 state 의 초기값을 지정하면 해결됩니다. 빈배열은 그 자체로 ture 이기 때문에 첫 빈 배열일 때 오류가 나지 않고 두번째 렌더링으로 넘어가면서 useEffect 값을 가져옵니다. (info는 객체의 느낌을 주므로 list 나 products 같은 복수형이 적당함)
const [products, setProducts] = useState([]); // 초기값 빈배열 넣기!
useEffect(() => {
fetch('/data/productInfo.json')
.then(res => res.json())
.then(res => setProducts(res));
}, []);