
[React] ReactJS로 영화 웹 서비스 만들기 (3)
Lpla
·2021. 2. 9. 22:14
반응형
#2 JSX & PROPS
컴포넌트(component)
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
app.js
function App() {
return (
<div className="App">
안녕하세요.
</div>
);
}
export default App;
- <App /> 은 컴포넌트(component)이다.
- 컴포넌트는 html을 반환하는 함수다.
- javscript와 html 사이의 이러한 조합을 JSX라고 한다.
- 이 jsx라는 것은 React에서만 쓰이는 유일한 개념이다.
컴포넌트 만들기
- src 폴더 안에 원하는 이름의 js파일을 생성한다. (나는 Latte.js로 만들었다.)
- 컴포넌트를 생성할 때마다 상단에
import React from "react";
를 작성해야 하지만 현재 기준으로 자동인식되기 때문에 하지 않아도 된다.
Latte.js
function Latte() {
return <h1>라떼는 맛있다!</h1>;
}
export default Latte;
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import Latte from './Latte';
ReactDOM.render(
<React.StrictMode>
<App /><Latte />
</React.StrictMode>,
document.getElementById('root')
);
- 강의에서는 <App /> 과 <Latte /> 를 붙여 놓을 경우 에러가 발생했지만 지금은 그 오류가 나오지 않는다.
- 그 이유는 <React.StrictMode> 때문인데 이것을 지우면 똑같은 에러가 발생한다.
- 에러가 발생한다면 App.js 안에 <Latte /> 를 호출하면 된다.
컴포넌트에 정보 보내기
- 방금 생성한 Latte.js 를 삭제하고 코드를 수정한다.
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<App />,
document.getElementById('root')
);
App.js
function App() {
return (
<div className="App">
<h1>안녕하세요!</h1>
<Latte />
</div>
);
}
function Latte() {
return <h2>라떼는 맛있다!</h2>
}
export default App;
- jsx로 Latte 함수를 만들어 <Latte /> 컴포넌트에 정보를 보낸 것이다.
function Latte() {...}
가 없을 경우 에러가 발생한다.
Prop (Properties)
App.js
function Coffee() {
return <h2>라떼는 맛있다!</h2>
}
function App() {
return (
<div className="App">
<h1>안녕하세요!</h1>
<Coffee fav="Latte"/>
</div>
);
}
export default App;
- Coffee 컴포넌트(Component)에 fav라는 프로퍼티(Property)를 Latte 라는 값(Value)으로 주었다.
<Coffee fav="Latte" hate="Espresso" soso="GreenTee"/>
- 당연히 여러 개의 Props를 만들 수 있고 콘솔로그로 호출하면 인자를 확인할 수 있다.
function Coffee(props) {
console.log(props);
return <h2>라떼는 맛있다!</h2>
}
function Coffee(props) {
console.log(props);
return (
<div>
<h2>{props.fav}는 맛있다!</h2>
<h2>{props.hate}는 맛없다!</h2>
<h2>{props.soso}는 평범하다.</h2>
</div>
);
}
function Coffee({fav}) {
return (
<div>
<h2>{fav}는 맛있다!</h2>
</div>
);
}
function App() {
return (
<div className="App">
<h1>안녕하세요!</h1>
<Coffee fav="Latte" />
<Coffee fav="Espresso" />
<Coffee fav="GreenTee" />
</div>
);
}
export default App;
- 이런 식으로 활용 가능하다. (여기까지도 쉬운 것 같다.)
Map을 이용한 효율적인 컴포넌트 생성
- 위 방법은 <Coffe fav=""> 를 계속 생성해야 하는 번거로운 작업이 필요하다.
- 우리는 데이터를 동적으로 생성하는 법을 알아야 한다.
- 먼저 필요한 데이터가 미리 존재한다고 가정하기 위해서 사전 작업이 필요하다.
const CoffeeList = [
{
name : "Latte",
image : "https://image.istarbucks.co.kr/upload/store/skuimg/2015/08/[110569]_20150813221315652.jpg"
},
{
name : "Americano",
image : "https://image.istarbucks.co.kr/upload/store/skuimg/2015/08/[110563]_20150813222100303.jpg"
},
{
name : "Cappuccino",
image : "https://image.istarbucks.co.kr/upload/store/skuimg/2015/08/[110601]_20150803101742023.jpg"
},
{
name : "Caffe Mocha",
image : "https://image.istarbucks.co.kr/upload/store/skuimg/2015/08/[46]_20150803105115048.jpg"
},
{
name : "Espresso",
image : "https://image.istarbucks.co.kr/upload/store/skuimg/2015/08/[20]_20150813221922951.jpg"
}
]
// 이미지 출처 : 스타벅스
- CoffeeList라는 객체(Object)를 만들었고 이것을 배열(Arroay)로 가져오고 렌더링 하기 위해 Map이 필요하다.
- 다행히 Map은 이전에 공부한 적이 있어서 참고할 수 있었다.
function Coffee({fav, picture}) {
return (
<div>
<h2>{fav}는 맛있다!</h2>
<img src={picture} />
</div>
);
}
function App() {
return (
<div className="App">
{CoffeeList.map(menu => <Coffee fav={menu.name} picture={menu.image} />)}
</div>
);
}
- JSX에서 중괄호를 사용하여 자바스크립트를 사용할 수 있다. 중괄호가 없다면 일반 텍스트.
- map과 화살표함수를 사용하여 fav와 picture이라는 프로퍼티에 각각 menu.name과 menu.image 값을 주었다.
다른 방법도 있다.
- 위 방법 말고 아래처럼 코드를 짤 수도 있다.
- 가독성은 좀 더 좋을 지 몰라도 함수를 하나 더 만들어야 하는 단점이 있다.
function Coffee({fav, picture}) {
return (
<div>
<h2>{fav}는 맛있다!</h2>
<img src={picture} />
</div>
);
}
function renderCoffee(list) {
return <Coffee fav={list.name} picture={list.image} />
}
function App() {
return <div>{CoffeeList.map(renderCoffee)}</div>
}
key prop 에러
- 방금 코드는 이런 방법도 있다는 설명을 위한 용도였고 다시 이전의 코드로 돌아간다.
- Console을 보면 에러가 하나 있다.
- Each child in a list should have a unique "key" prop.
- 즉 각각의 고유한 Key를 만들어줘야 한다.
function Coffee({fav, picture}) {
return (
<div>
<h2>{fav}는 맛있다!</h2>
<img src={picture} />
</div>
);
}
const CoffeeList = [
{
id:1,
name : "Latte",
image : "https://image.istarbucks.co.kr/upload/store/skuimg/2015/08/[110569]_20150813221315652.jpg"
},
{
id:2,
name : "Americano",
image : "https://image.istarbucks.co.kr/upload/store/skuimg/2015/08/[110563]_20150813222100303.jpg"
},
{
id:3,
name : "Cappuccino",
image : "https://image.istarbucks.co.kr/upload/store/skuimg/2015/08/[110601]_20150803101742023.jpg"
},
{
id:4,
name : "Caffe Mocha",
image : "https://image.istarbucks.co.kr/upload/store/skuimg/2015/08/[46]_20150803105115048.jpg"
},
{
id:5,
name : "Espresso",
image : "https://image.istarbucks.co.kr/upload/store/skuimg/2015/08/[20]_20150813221922951.jpg"
}
]
id라는 key를 만들었지만 함수에서 인자로 사용하고 있지 않기 때문에 실제로 출력되진 않는다.
alt 생성
- 코드를 자세히 보면 물결무늬로 경고가 뜨고 있다. 커서를 올려 확인해보면 alt 요소가 없기 때문이다.
- alt 요소는 일반인들은 거의 사용하지 않는다. 엑박이 떴을 때나 볼 수 있지 그 외에는 마주할 일이 없다.
- 시각장애인들에게 이미지를 설명하는 용도로 쓰이는데 웹에서는 사용하길 권장하고 있다.
function Coffee({fav, picture}) {
return (
<div>
<h2>{fav}는 맛있다!</h2>
<img src={picture} alt={fav} />
</div>
);
}
- 간단히 alt를 작성하면 경고표시는 사라진다.
prop 점검하기(prop-types)
- 현재 갖고 있지 않은 prop을 출력할 경우 당연히 에러가 발생한다.
- 우리는 사람이기 때문에 실수를 하고 이를 방지할 수 있는 무언가가 필요하다.
- prop-types는 내가 전달받은 props가 내가 원하는 타입인지 확인할 때 쓰인다.
npm i prop-types
- package.json에 보면 설치된 것을 확인할 수 있다.
import propTypes from "prop-types"
Coffee.propTypes = {
fav: propTypes.string.isRequired,
picture: propTypes.string.isRequired
}
- 상단에 설치한 prop-types를 import하고
fav: propTypes.string.isRequired
로 string인지 타입을 확인할 수 있다. - 이때 대소문자를 잘 지키도록 하자. 이 부분에서 틀려 오류가 발생하는 사람들이 많다.
- 이런 오류가 발생하면 타입이 잘못된 것이고 콘솔이 뜨지 않는다면 정상적이다.
전체 코드 (App.js)
import propTypes from "prop-types"
Coffee.propTypes = {
fav: propTypes.string.isRequired,
picture: propTypes.string.isRequired,
rating: propTypes.string.isRequired,
}
const CoffeeList = [
{
id:1,
name : "Latte",
image : "https://image.istarbucks.co.kr/upload/store/skuimg/2015/08/[110569]_20150813221315652.jpg",
rating: 5
},
{
id:2,
name : "Americano",
image : "https://image.istarbucks.co.kr/upload/store/skuimg/2015/08/[110563]_20150813222100303.jpg",
rating: 4.2
},
{
id:3,
name : "Cappuccino",
image : "https://image.istarbucks.co.kr/upload/store/skuimg/2015/08/[110601]_20150803101742023.jpg",
rating: 3
},
{
id:4,
name : "Caffe Mocha",
image : "https://image.istarbucks.co.kr/upload/store/skuimg/2015/08/[46]_20150803105115048.jpg",
rating: 4.7
},
{
id:5,
name : "Espresso",
image : "https://image.istarbucks.co.kr/upload/store/skuimg/2015/08/[20]_20150813221922951.jpg",
rating: 1
}
]
function App() {
return (
<div className="App">
{CoffeeList.map(menu => <Coffee key={menu.id} fav={menu.name} picture={menu.image} rating={menu.rating}/>)}
</div>
);
}
export default App;
반응형