프로그래밍/React JS

[영화 웹 서비스 만들기] #2 JSX & PROPS ( Component, forEach(), filter(), map() )

그릿_GRIT 2021. 4. 2. 15:42
320x100

 

 

본 포스팅은 리액트 JS를 다루고 있습니다.

# 2.0 Creating your first React Component

Localhost

Localhost를 게속 유지하고 창을 계속 띄운 상태로 실행시키고 싶다면 npm start 를 하고 console을 종료하지 않아야 한다. x를 눌러서 숨기는 경우는 계속 작동한다. console만 종료시키지 않으면 된다.

JSX (1)

JS와 HTML의 조합을 JSX라고 한다. React에서 나온 거의 유일한 개념이다.

 

 

위의 <APP />는 HTML이 아니다. 아래의 return 안에 있는 내용들은 HTML이다.

Component

 

 

위의 <APP /> 과 같은 것들을 Component라고 한다. react는 component와 함께 동작한다. component를 만들고 보기좋게 만들며 component가 data를 보여주게 할 것이다. component는 HTML을 반환하는 함수이다.

<APP /> 부분은 우리가 component를 사용하고자 할 때의 형태이다. App ← 이런 형태로 적으면 react가 알아들을 수 없다.

Component 만들기

  • src폴더 안에 (만들고 싶은 component의 이름).js를 생성한다.
  • component를 작성할 때마다 import React from "react";를 써줘야 한다. (만약 하지 않으면 react는 여기에 JSX가 있는 component를 사용하는 것을 이해하지 못한다.)
  • 파일이름으로 함수를 만든다. (대문자로 파일명 시작했으면 앞글자 대문자로 함수를 만든다.)
  • export한다. 코드는 export default 함수이름; .

Component 생성 및 사용 예제 코드

//Potato.js
import React from "react";

function Potato(){
    return <h3>I love Potato!!</h3>;
}

export default Potato;
//index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import Potato from "./Potato";

ReactDOM.render(<App /><Potato />, document.getElementById("root"));

위의 코드에서 import를 할 때 "./파일명"를 사용했는데, 여기서 .의 의미는 작성하고 있는 현재 파일과 같은 directory에 있을 때를 말한다.

 

 

현재 쓰고 있는 파일이 App.js라 가정해보자. 만약 App.js에 index.js나 Potato.js를 import 하고 싶다면 이 파일은 모두 App.js와 같은 위치 (모두 src 파일안에 위치하고 서로 상하 문서 관계에 있지 않다. )에 있으므로 이럴 때 "./파일명"을 통해 파일을 불러올 수 있다.

 

 

 

 

 

 

 

 

 

주의사항

위의 예제코드에서 ReactDom.render(<App /><Potato />, document.getElementById("root"));처럼 component를 두 개이상 사용할 수 없다. 만약 사용하면 아래와 같은 failed to compile이 뜬다.

 

 

따라서 이러한 문제를 해결하기 위해서는 <Potato />를 <App /> 옆에 두는 대신에 App 안에 넣어야 한다. 이럴 경우 사용하고자 하는 component는 App에서만 import 해주면 된다.

 

 

맞는 코드

// index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

ReactDOM.render(<App />, document.getElementById("root"));
// App.js
import React from "react";
import Potato from "./Potato";

function App() {
  return (
    <div>
      <h1>hello!!</h1>
      <Potato />
    </div>
  );
}

export default App;
// Potato.js
import React from "react";

function Potato(){
    return <h3>I love Potato!!</h3>;
}

export default Potato;

 

 

#2.1 Reusable Components with JSX + Props

파일 생성 없이 component 생성 및 사용

import React from "react";

function Potato(){
  return <h1>I like potato</h1>;
}

function App() {
  return (
    <div>
      <h1>hello!!</h1>
      <Potato />
    </div>
  );
}

export default App;

위와 같이 component를 JS에서 함수를 추가하는 것처럼 같은 파일에 정의를 한 뒤 App component에 추가해주면 굳이 파일을 새로 만들지 않아도 만들고 사용할 수 있다.

JSX (2)

정보 전달 (Component에 정보를 보낼 수 있다.)

react는 재사용 가능한 component를 만들어 계속 반복해서 사용할 수 있다. 따라서 아래와 같이 할 필요가 없어진다.

import React from "react";

function Movie(){
  return <h1>I like potato</h1>;
}

function App() {
  return (
    <div>
      <h1>hello!!</h1>
      <Movie />
      <Movie />
      <Movie />
      <Movie />
      <Movie />
    </div>
  );
}

export default App;

이렇게 복사 붙여 넣기를 반복할 필요가 없다.

Component 간에 정보를 주고 받기 위해 마치 HTML처럼 어떤 것의 속성에 값을 주는 형식으로 쓴다. 예시는 아래 코드와 같다.

import React from "react";

function Food(){
  return <h1>I like potato</h1>;
}

function App() {
  return (
    <div>
      <h1>hello!!</h1>
      <Food fav="kimchi"/>
    </div>
  );
}

export default App;

Food Component에 kimchi라는 value로 prop(=property) fav을 줬다.

넘기는 정보는 위 처럼 "kimchi"라는 string 뿐만 아니라 something={true}처럼 boolean값을 넘길 수도 있고 papapa={["hello", 1,2,3,4, true]} 처럼 array를 넘길 수도 있다. 이러한 방식으로 father component에서 children component로 원하는 많은 속성(property)를 보낼 수 있다.

누군가가 food component로 정보를 보내려고 하면 (<Food fav="kimchi" />를 쓰면) react는 이 속성을 가져와 food function component의 argument(인자)로 넣게 될 것이다.

import React from "react";

function Food(prop){
  console.log(prop);
  return <h1>I like potato</h1>;
}

function App() {
  return (
    <div>
      <h1>hello!!</h1>
      <Food name="kimchi" something={true} papapa={["hello",1,2,3, true ]} />
    </div>
  );
}

export default App;

 

 

위 처럼 object로 해당 속성(prop)을 받는다.

function Food(prop){
  console.log(prop.fav);
  return <h1>I like potato</h1>;
}

function App() {
  return (
    <div>
      <h1>hello!!</h1>
      <Food fav="kimchi" />
    </div>
  );
}

위와 같이 속성이 하나라도 prop이라는 object를 받고 그 안에 fav가 있는 것이므로 prop.fav라고 써야 해당 내용이 출력된다. 만약 바로 fav를 쓰고 싶다면 {fav}와 같이 {}을 이용하고 그 안에 property의 이름을 쓰면 된다.

import React from "react";

function Food({fav}){
  console.log({fav});
  return <h1>I like potato</h1>;
}

function App() {
  return (
    <div>
      <h1>hello!!</h1>
      <Food fav="kimchi" />
    </div>
  );
}

export default App;

{}안에 속성의 이름을 쓰지 않고 다른 것을 쓰게 된다면 그 속성은 정의 되지 않았으므로 undefined라고 뜬다. 따라서 속성의 이름과 함수에서 인자로 받는 부분은 이름이 서로 같아야 한다.

 

예제

import React from "react";

function Food({ fav }){
  return <h1>I like { fav }</h1>;
}

function App() {
  return (
    <div>
      <h1>hello!!</h1>
      <Food fav="kimchi" />
    </div>
  );
}

export default App;

실행결과

 

 

이렇게 { fav }를 html요소 안에 넣어 활용할 수 있다.

 

 

#2.2 Dynamic Component Generation

동적인 데이터를 추가하는 방법

데이터를 object 형식으로 만들고 이를 모두 모아 배열로 저장한다. map을 써서 배열의 각 item 당 component 함수를 실행하도록 한다.

component 함수 안에서 return 안에 html요소들을 주로 쓰게 되는데 여기서 JS를 쓰고 싶다면 {}를 쓰고 그 안에 사용하면 된다.

 

👇🏻 [ JS 쓸 때 {}를 쓴다. → 예시코드 더보기 ]

더보기
function App() {
  return (
    <div>
      {console.log(foodILike.map(renderFood))}
      {foodILike.map(renderFood)}
    </div>
  );
}

실행 결과는 아래와 같이 React component가 들어있는 배열이 나온다.


import React from "react";

function Food({ name }) {
  return <h1>I like { name }</h1>;
}

const foodILike = [
  {
    name: "Kimchi",
    image:
      "http://aeriskitchen.com/wp-content/uploads/2008/09/kimchi_bokkeumbap_02-.jpg",
  },
  {
    name: "Samgyeopsal",
    image:
      "https://3.bp.blogspot.com/-hKwIBxIVcQw/WfsewX3fhJI/AAAAAAAAALk/yHxnxFXcfx4ZKSfHS_RQNKjw3bAC03AnACLcBGAs/s400/DSC07624.jpg",
  },
  {
    name: "Bibimbap",
    image:
      "http://cdn-image.myrecipes.com/sites/default/files/styles/4_3_horizontal_-_1200x900/public/image/recipes/ck/12/03/bibimbop-ck-x.jpg?itok=RoXlp6Xb",
  },
  {
    name: "Doncasu",
    image:
      "https://s3-media3.fl.yelpcdn.com/bphoto/7F9eTTQ_yxaWIRytAu5feA/ls.jpg",
  },
  {
    name: "Kimbap",
    image:
      "http://cdn2.koreanbapsang.com/wp-content/uploads/2012/05/DSC_1238r-e1454170512295.jpg",
  },
];

function App() {
  return (
    <div>
      <h1>Hello!!</h1>
      {foodILike.map(dish => <Food name = {dish.name}/>)}
    </div>
  );
}

export default App;

위의 코드를 예시를 들어 설명하면 foodILike이라는 배열을 만들고 데이터를 저장한다. 전체 틀이 되는 App component 함수의 return에서 foodILike을 map 함수를 사용해서 각 item을 object 형식으로 불러온다. 그 다음 Food component를 작성해서 해당 내용이 Food component 함수로 보내지게끔 한다. 보내진 정보는 Food component 함수에서 return 값으로 html 요소를 반환하면서 그 내용이 최종적으로 화면으로 출력된다.

 

결과

 

 

array.map()

map은 인자로 실행시키고자 하는 함수를 주고 array자리에는 /우리가 그 함수를 실행시켜 적용하고자 하는 배열이름을 주면 된다. map은 array의 각 item들에 인자로 준 함수를 실행시키고 그 결과 값을 배열로 만들어 리턴한다.

 

 

위의 경우에는 배열의 각 item 별로 console.log를 실행하고 0을 리턴했다. 결과 값은 결국 0이므로 4번의 0이 배열로 만들어 map의 결과 값으로 최종 리턴 되었다. 하지만 원본 friends 배열이 0으로 바뀐건 아니다.

 

 

👇🏻 [ 차이점 자세히 보기 ]

더보기

forEach()

map()

return 값이 없는 경우

return 값이 없으면 undefined로 실행결과를 내고 이것을 배열로 만들어 map의 반환값으로 최종 return 한다.

return 값이 있는 경우


예제 실행 코드

 

 

두 개 이상의 정보 넘기기

import React from "react";

function Food({ name , picture }) {
  return (
    <div>
      <h2>I like {name}</h2>
      <img src={picture} />
    </div>
  );
}

const foodILike = [
  {
    name: "Kimchi",
    image: "http://aeriskitchen.com/wp-content/uploads/2008/09/kimchi_bokkeumbap_02-.jpg"
  },
  {
    name: "Samgyeopsal",
    image: "https://3.bp.blogspot.com/-hKwIBxIVcQw/WfsewX3fhJI/AAAAAAAAALk/yHxnxFXcfx4ZKSfHS_RQNKjw3bAC03AnACLcBGAs/s400/DSC07624.jpg"
  },
  {
    name: "Bibimbap",
    image: "http://cdn-image.myrecipes.com/sites/default/files/styles/4_3_horizontal_-_1200x900/public/image/recipes/ck/12/03/bibimbop-ck-x.jpg?itok=RoXlp6Xb"
  },
  {
    name: "Doncasu",
    image: "https://s3-media3.fl.yelpcdn.com/bphoto/7F9eTTQ_yxaWIRytAu5feA/ls.jpg"
  },
  {
    name: "Kimbap",
    image: "http://cdn2.koreanbapsang.com/wp-content/uploads/2012/05/DSC_1238r-e1454170512295.jpg"
  }
];

function App() {
  return (
    <div>
      {foodILike.map((dish) => (
        <Food name={dish.name} picture= {dish.image} />
      ))}
    </div>
  );
}

export default App;

위와 같이 두 개 이상의 정보를 넘기고 싶다면 { name }, { picture }꼴이 아니라 { name, picture } 이렇게 써야 한다.

실행결과

 

 

위의 코드에서 인자에 함수를 썼던 것을 밖에 함수로 빼서 쓰면 아래와 같이 코드를 수정할 수 있다.

function renderFood(dish){
  return <Food name={dish.name} picture={dish.image} />

}

function App() {
  return (
    <div>
      {foodILike.map(renderFood)}
    </div>
  );
}

 

320x100