- 음식 앱 만지고 고치기
- 음식 앱에 prop-types 도입하기
1. 음식 앱 만지고 고치기
코드블럭처럼 코드를 수정해준다.
function App() {
return (
<div>
{foodLike.map(dish => (
<Food name={dish.name} picture={dish.image} />
))}
</div>
);
}
===========================================
// 다음 처럼 변경한다.
function App() {
return (
<div>
{foodLike.map(renderFood)}
</div>
);
}
- renderFood() 함수를 정의한다.
앞선 코드 위에 renderFood() 함수를 정의 해준다.
function renderFood(dish) {
return <Food name={dish.name} picture={dish.image} />;
}
function App() {
return (
<div>
{foodLike.map(renderFood)}
</div>
);
}
map() 함수의 첫 번째 인자로 전달한 화살표 함수를 밖으로 빼서
일반 함수 rederFood() 로 바꾼것 뿐이라 바뀌는 것은 없다.
만약 renderFood() 함수를 화살표 함수로 바꾸고 싶다면 아래 코드블럭 처럼 써주자.
const renderFood = dish => <Food name={dish.name} picture={dish.image} />;
- 현재까지의 코드 상태 -
import React from 'react';
function Food({ name, picture }) {
return (
<div>
<h2>I like {name} </h2>
<img src={picture} />
</div>
);
}
const foodLike = [이미지 주소들];
function renderFood(dish) {
return <Food name={dish.name} picture={dish.image} />;
}
function App() {
return (
<div>
{foodLike.map(renderFood)}
</div>
);
}
export default App;
- map() 함수 반환값 확인
console.log(foodLike.map(...)); 추가해준다.
function App() {
console.log(foodLike.map(renderFood));
return (
<div>
{foodLike.map(renderFood)}
</div>
);
}
※개발자 도구에서 console.log 가 안보이고,
[HMR] Waiting for update signal from WDS
https://simfairy.tistory.com/161
Array(5)가 보인다.
화살표를 눌러서 펼쳐보면 사진 처럼 나온다.
이게 map() 함수가 반환한 리액트 컴포넌트다.
반환값을 확인하기 위해서 한것이니 확인을 했다면 코드를 원상태로 돌리자.
삭제
function renderFood(dish) {
return <Food name={dish.name} picture={dish.image} />;
}
코드 원상 복구
function App()
return (
<div>
{foodLike.map(dish => (
<Food name={dish.name} picture={dish.image} />
))}
</div>
);
}
- 삭제 라고 적힌 코드는 지워주고,
- 코드 원상 복구라고 적힌 부분은 다시 코드블럭처럼 돌려놓는다.
개발자 도구에 Warning: Each child in a list should have a unique "key" prop. 오류가 보일텐데
이유는 리스트의 각 원소는 유일한 key prop을 가져야 한다고 한다.
배열 속성에 key 값이 없어서 이런 오류가 나온것.
리액트 원소는 유일해야 하는데 리스트에 포함되면서 유일성이 없어졌다.
- 해결을 위해서는 foodLike 배열 원소에 id 값을 추가해준다.
const foodLike = [
{
id: 1,
name: 'Kimchi',
image: 'https://cdn.pixabay.com/photo/2019/07/25/01/35/kimchi-4361465_1280.jpg',
},
{
id: 2,
name: 'Samgyeopsal',
image: 'https://cdn.pixabay.com/photo/2017/05/18/10/48/pork-2323228_1280.jpg',
},
.
.
.
{
id: 5
name: 'Kimbap',
image: 'https://cdn.pixabay.com/photo/2015/03/24/07/07/kim-rice-687172_1280.jpg',
},
];
id를 추가하는 이유는 컴포넌트가 서로 다르다는 것을 알려주기 위해
컴포넌트에 key props를 추가한다.
- Food 컴포넌트에 key props를 추가한다.
{dish.id}를 전달하면 된다.
function App()
return (
<div>
{foodLike.map(dish => (
<Food key={dish.id} name={dish.name} picture={dish.image} />
))}
</div>
);
}
리액트 앱을 다시 실행하고 콘솔창을 열어보면 오류가 없어졌다.
※단, key props는 리액트 내부에서 사용되는 특수한 prop라서
Food 컴포넌트에 직접 전달되지 않는다.
만약 alt-text 관련 오류가 보인다면
function Food({ name, picture }) {
return (
<div>
<h2>I like {name} </h2>
<img src={picture} alt={name} />
</div>
);
}
img src={picture} 뒤에 alt={name} 를 추가하자.
블로그 글 9 - 발전된 컴포넌트 만들기(1) 에서 언급했음.
2. 음식 앱에 prop-types 도입하기
- props 검사하기
- 음식 데이터에 rating(평점) 추가
foodLike 배열 각 요소에 rating을 추가하자.
자료형은 Number 다.
const foodLike = [
{
id: 1,
name: 'Kimchi',
image: 'https://cdn.pixabay.com/photo/2019/07/25/01/35/kimchi-4361465_1280.jpg',
rating: 5,
},
{
id: 2,
name: 'Samgyeopsal',
image: 'https://cdn.pixabay.com/photo/2017/05/18/10/48/pork-2323228_1280.jpg',
rating: 4.3,
},
.
.
.
{
id: 5,
name: 'Kimbap',
image: 'https://cdn.pixabay.com/photo/2015/03/24/07/07/kim-rice-687172_1280.jpg',
rating: 4.6,
},
];
rating은 준비됐고, props 자료형을 검사할 수 있는 prop-types를 설치한다.
- prop-types 설치
1.
터미널에서 코드블럭에 있는 명령어를 입력한다.
경로는 현재 react 프로젝트가 있는곳에서 한다.
npm install prop-types
2.
package.json을 연다.
"prop-types": 부분이 보이면 잘 설치 된것.
prop-types은 전달 값이 내가 원하는 값인지 확인 해준다.
어떠한 값이 전달 되야한다고 정의 할 수 있다.
- prop-types 적용
App.js 파일 맨위에 다음을 추가해준다.
import PropTypes from 'prop-types';
이어서 다른 부분에도 코드들을 추가해준다.
import React from 'react';
import PropTypes from 'prop-types';
function Food({ name, picture, rating }) {
return (
<div>
<h2>I like {name} </h2>
<h4>{rating}/5.0</h4>
<img src={picture} alt={name} />
</div>
);
}
const foodLike = [...];
function App() {
return (
<div>
{foodLike.map(dish => (
<Food key={dish.id} name={dish.name} picture={dish.image} rating={dish.rating} />
))}
</div>
);
}
export default App;
여기까진 prop-types를 적용하진 않은 상태다.
그래도 rating props로 전달한 값은 출력된다.
이제 prop-types를 적용해보자.
function App() {
return (
<div>
{foodLike.map(dish => (
<Food key={dish.id} name={dish.name} picture={dish.image} rating={dish.rating} />
))}
</div>
);
}
Food.propTypes = {
name: PropTypes.string.isRequired,
picture: PropTypes.string.isRequired,
rating: PropTypes.string.isRequired,
};
export default App;
Food.propTypes = {...}를 추가한다.
1. 자료형 오류
그리고 앱을 다시 실행해보면 문제없이 실행되는데 콘솔창을 보면 경고 메시지가 뜬다.
Warning: Failed prop type: Invalid prop `rating` of type `number` supplied to `Food`, expected `string`.
앞서 추가한 코드에 rating: PropTypes.string.isRequired 다.
string은 '문자열', isRequired는 '필요하다' 라는 뜻이다.
근데 지금 넘겨준 자료형은 Number다. 그래서 오류가 뜬것.
- prop-types 경고 해결
Food.propTypes = {
name: PropTypes.string.isRequired,
picture: PropTypes.string.isRequired,
rating: PropTypes.number.isRequired,
};
rating: propTypes.string 이었던걸 number로 바꾼다.
2. 이름 값 오류
function App() {
return (
<div>
{foodLike.map(dish => (
<Food key={dish.id} name={dish.name} image={dish.image} rating={dish.rating} />
))}
</div>
);
}
<Food picture={} 를 image={}로 바꿔보자
picture가 포함되어야 하는데 찾을수 없다는 오류를 보여준다.
그리고 이미지들도 표시 되지않는다.
다시 코드를 원래대로 돌려놓자.
function App() {
return (
<div>
{foodLike.map(dish => (
<Food key={dish.id} name={dish.name} picture={dish.image} rating={dish.rating} />
))}
</div>
);
}
- rating: 의 .isRequired를 제거해보자
Food.propTypes = {
name: PropTypes.string.isRequired,
picture: PropTypes.string.isRequired,
rating: PropTypes.number
};
이제 rating props는 필수가 아니어도 되는 항목이란 뜻이다.
단, 값이 전달될 때는 자료형이 number이긴 해야함.
- 현재 상태 코드 -
import React from 'react';
import PropTypes from 'prop-types';
function Food({ name, picture, rating }) {
return (
<div>
<h2>I like {name} </h2>
<h4>{rating}/5.0</h4>
<img src={picture} alt={name} />
</div>
);
}
const foodLike = [
{
id: 1,
name: 'Kimchi',
image: 'https://cdn.pixabay.com/photo/2019/07/25/01/35/kimchi-4361465_1280.jpg',
rating: 5,
},
{
id: 2,
name: 'Samgyeopsal',
image: 'https://cdn.pixabay.com/photo/2017/05/18/10/48/pork-2323228_1280.jpg',
rating: 4.3,
},
{
id: 3,
name: 'Bibimbap',
image: 'https://cdn.pixabay.com/photo/2017/08/08/09/44/food-photography-2610863_1280.jpg',
rating: 4.9,
},
{
id: 4,
name: 'Doncasu',
image: 'https://cdn.pixabay.com/photo/2016/09/23/23/23/restaurant-1690696_1280.jpg',
rating: 4.2,
},
{
id: 5,
name: 'Kimbap',
image: 'https://cdn.pixabay.com/photo/2015/03/24/07/07/kim-rice-687172_1280.jpg',
rating: 4.6,
},
];
function App() {
return (
<div>
{foodLike.map(dish => (
<Food key={dish.id} name={dish.name} picture={dish.image} rating={dish.rating} />
))}
</div>
);
}
Food.propTypes = {
name: PropTypes.string.isRequired,
picture: PropTypes.string.isRequired,
rating: PropTypes.number.isRequired,
};
export default App;
prop-types의 다양한 사용법을 알고 싶다면
prop-types 공식문서에 usage 부분을 보고 참고하자.
github.com/facebook/prop-types
facebook/prop-types
Runtime type checking for React props and similar objects - facebook/prop-types
github.com
'Project > REACT' 카테고리의 다른 글
12 - state와 클래스형 컴포넌트(2) (0) | 2020.12.18 |
---|---|
11 - state와 클래스형 컴포넌트(1) (0) | 2020.12.17 |
9 - 발전된 컴포넌트 만들기(1) (0) | 2020.12.10 |
8 - 리액트 기초 개념: props (0) | 2020.12.08 |
7 - 리액트 기초 개념: 컴포넌트, JSX (0) | 2020.12.08 |
댓글