[항해99 리액트 입문] 07~9. Props

posinity·2022년 11월 26일

07. Props Part 1

Props란?

부모 컴포넌트로부터 받아온 데이터

// src/App.js

import React from "react";

function App() {
  return <GrandFather />;
}

function GrandFather() {
  return <Mother />;
}

function Mother() {
	const name = '홍부인';
  return <Child />; // Mother
}

function Child() {
  return <div>연결 성공</div>;
}


export default App;

Props로 값 전달하기

우리는 컴포넌트 간의 정보를 교류할 때 Props를 사용합니다. 다른 컴포넌트는 생략하고 Mother만 봅시다. 만약 Mother 컴포넌트가 가지고 있는 정보(값)를 Child에게 주고 싶을 때는 아래 코드와 같이 합니다.

motherName이라는 이름으로 name 값을 Child 컴포넌트에게 전달해준 것입니다. 우리는 이 과정을 “Props 로 정보를 전달했다” 라고 표현합니다.

// src/App.js
import React from "react";

function App() {
  return <GrandFather />;
}

function GrandFather() {
  return <Mother />;
}

function Mother() {
	const name = '홍부인';
  return <Child motherName={name} />; // 💡"props로 name을 전달했다."
}

function Child() {
  return <div>연결 성공</div>;
}

export default App;

Props로 데이터 받기

그러면, Mother가 전달해준 motherName은 Child가 어떻게 받을 수 있을까요? 이렇게 받습니다. 우리가 지금까지 한번도 관심있게 들여다보지 않았던 컴포넌트의 인자에서 props의 값을 받을 수 있습니다. 한번 콘솔에 찍어볼까요?

function Child(props){ //매개변수로 props 적어주기
	console.log(props) //콘솔로 확인해보기
	return <div>연결 성공</div>
}

아래 사진처럼 Mother가 보내준 정보가 객체 형태로 보이게 된다.
props란 결국 부모 컴포넌트가 자식에게 넘겨준 데이터들의 묶음이다.

Props 데이터 출력하기

import React from "react";

// div안에서 { } 를 쓰고 props.motherName을 넣어보세요.
function Child(props) {
  return <div>{props.motherName}</div>;
}

function Mother() {
  const name = "홍부인";
  return <Child motherName={name} />;
}

function GrandFather() {
  return <Mother />;
}

function App() {
  return <GrandFather />;
}

export default App;


값이 화면에 찍히게 된다.

propsobject literal 형태이기 때문에 {props.motherName} 로 꺼내서 사용할 수 있다. object literalkeymotherName 인 이유는 우리가 Child로 보내줄 때 motherName={name} 으로 보내주었기 때문.

object literal{key: “value”} 데이터 형태를 의미합니다. 더 자세한 설명

JSX에서는 HTML만 쓸 수 있는 줄 알았는데, 자바스크립트 코드를 사용했죠? 맞습니다. JSX에서도 { } 중괄호를 사용하면 자바스크립트 코드를 사용할 수 있습니다.

자식 컴포넌트에서는 부모 컴포넌트로 props를 전달할 수 없음. 오직 부모 컴포넌트에서 자식 컴포넌트로만 props를 전달할 수 있다.

퀴즈

  • GrandFather 컴포넌트에서 GrandFatherName을 만들어서 화면에 렌더링 해봅시다.
  • src 폴더 안에 App.js 에 있는 내용을 모두 지우고 새롭게 작성해봅니다.

정답

// src/App.js

import React from "react";

function App() {
  return <GrandFather />;
}

function GrandFather() {
  const name = "할아버지"; //GrandFather 컴포넌트에 이름 설정
  return <Mother grandFatherName={name} />; 
  // Mother 컴포넌트에 grandFatherName이란 키에 name값 주기
}

//GrandFather 컴포넌트에서 props 받아오기
function Mother(props) { 
  return <Child grandFatherName={props.grandFatherName} />; 
}
//Child 컴포넌트에 grandFatherName 이라는 이름으로 props의 grandFatherName 값 주기


 //Mother 컴포넌트에서 props 받기
function Child(props) {
  return <div>{props.grandFatherName}</div>; 
}
// props의 grandFatherName 값 출력하기

export default App;

파라미터 값은 꼭 Props로 해야 하나?

아니다!

function Child(aaa) {
  return <div>{aaa.grandFatherName}</div>; 
}

이렇게 파라미터 값을 바꿔줘도 잘 동작함

구조분해할당 가능

function Child(props) {
  const { grandfatherName } = props; 
  //props 데이터를 구조분해할당해줌
  console.log(grandfatherName); //할아버지 라고 찍힘
  return <div>{grandfatherName}</div>; //그대로 할아버지라고 찍힘
}

더 알아보면 좋은 키워드

  1. Props Drilling 이란, 무엇인가?
    props를 오로지 하위 컴포넌트로 전달하는 용도로만 쓰이는 컴포넌트들을 거치면서 React Component 트리의 한 부분에서 다른 부분으로 데이터를 전달하는 과정.
    우선 Prop Drilling 는 문제가 되지 않습니다. prop 전달이 3~5개 정도의 컴포넌트라면 말이죠.
    하지만 prop 전달이 10개, 15개 같이 더 많은 과정을 거치게 된다면 어떻게 될까요? 코드를 읽을 때 해당 prop을 추적하기 힘들어집니다.
    그렇기 때문에 유지보수도 더욱 어려워집니다.
  2. prop Types

08. Props Part 2

부모 컴포넌트로 정보를 전달하는 children

<Component props={props} />
와 다른 방식으로 자식 컴포넌트에 정보를 전달해주어도 사용 할 수 있는 props가 있습니다. 바로 children 입니다.

// src/App.js

import React from "react";

function User() {
  return <div></div>;
}

function App() {
  return <User>안녕하세요</User>;
}
export default App;

App.js에 App 컴포넌트와 User 컴포넌트가 있습니다. 그리고 App 컴포넌트가 User 컴포넌트를 자식으로 품고 있습니다. 그리고 User 컴포넌트 사이에 ‘안녕하세요' 라는 문장이 있습니다. 근데 yarn start 를 해서 화면을 보면 아무것도 화면에 표시되지 않습니다.

왜 그럴까요? 그 이유는 App 컴포넌트에서 ‘안녕하세요' 라는 정보를 보냈지만, User 컴포넌트에서는 그 정보를 받지 않았기 때문입니다.

우리는 부모 컴포넌트에서 정보를 보냈을 때, 자식 컴포넌트에서 그 정보를 사용하고 싶다면 props를 통해 정보를 받아와야 했습니다. 하지만 위 예시에서는 User 컴포넌트에서 그 정보를 받고 있지 않기 때문에 화면에 어떠한 문장도 보이지 않고 있는 것 입니다.

그런데 위 예시에서는 <User>안녕하세요</User> 이렇게 정보를 보내고 있습니다. <User hello='안녕하세요'> 이렇게 props를 보내던 방식과는 조금 다릅니다. 이것이 children props를 보내는 방식입니다. 그렇다면 자식 컴포넌트에서는 어떻게 정보를 받을까요? 정보를 받는 방식은 기존과 동일합니다. 대신 그 이름이 children 으로 정해져 있습니다. 아래 코드를 입력해보세요. 콘솔에 ‘안녕하세요'가 잘 보이시나요?

function User(props) {
	console.log(props.children)
  return <div></div>;
}

children 값 받아서 렌더링하기

자, 그럼 위에서의 코드를 수정해보겠습니다. User 컴포넌트에서 props.children을 받아 그대로 렌더링 해준 모습입니다. 이제 화면에 정상적으로 ‘안녕하세요’ 라는 문장이 보입니다!

import React from "react";

function User(props) {
  return <div>{props.children}</div>;
}

function App() {
  return <User>안녕하세요</User>;
}
export default App;

<User>안녕하세요</User> 자식을 불러오는 태그 사이에 들어간 데이터는 다 children 이라는 키의 값이 된다.

children의 용도

Layout 컴포넌트 안에는 header 라는 컴포넌트가 있고, header 아래에 {props.children} 를 통해서 props를 받아 렌더링 하고 있습니다. 즉, Layout 컴포넌트가 쓰여지는 모든 곳에서 … 안에 있는 정보를 받아서 가져올 수 있는 것이죠.

// src/About.js

import React from "react";
import Layout from "./components/Layout";

function App() {
  return (

    <Layout> 
      <div>여긴 App의 컨텐츠가 들어갑니다.</div>
    </Layout>
  );
}
export default App;

이 코드를 통해, Layout에 있는 header가 보여지게 되고, “여긴 App의 컨텐츠가 들어갑니다.” 라는 문장이 Layout의 props로 전달되는 것 입니다. 결과적으로 우리는 header 컴포넌트를 Layout 컴포넌트에서 한번만 작성하면 여러 페이지에서 모두 보여지게 할 수 있는 것 입니다.

Layout 컴포넌트를 About 컴포넌트에 또 사용했습니다. 어떤가요? children이 이해가 되시나요!?

// src/About.js

import React from "react";
import Layout from "./components/Layout";

function About() {
  return (
    <Layout> 
      <div>여긴 About의 컨텐츠가 들어갑니다.</div>
    </Layout>
  );
}
export default About;

더 알아보면 좋은 키워드

  • “children을 활용하여 컴포넌트 만들기” 알아보기

09. Props Part 3

구조분해 할당과 Props

우리는 지금까지 자식 컴포넌트에서 props를 받을 때 이렇게 했습니다.

function Todo(props){
	return <div>{props.todo}</div>
}

문제는 없지만 todo 라는 props를 사용하는 모든 곳에서 props. 를 붙여줘야만 했죠. 이것을 조금 더 짧게 쓰는 방법이 있습니다. 바로 자바스크립트의 구조 분해 할당을 이용하는 것 입니다. 앞서 설명했듯이 props는 object literal 형태의 데이터 입니다. 그래서 우리는 구조 분해 할당을 이용할 수 있습니다. 이렇게 말이죠.

function Todo({ title }){
	return <div>{title}</div>
}

여러개의 Props를 받는다면?

function Todo({ title, body, isDone, id }){
	return <div>{title}</div>
}

defaultProps

defaultProps란, 부모 컴포넌트에서 props를 보내주지 않아도 설정될 초기 값 입니다.

컴포넌트를 만들고 자식 컴포넌트에서 props를 받다보면, 자주 받거나 또는 무조건 받아야 하는 props들이 있습니다. 예를 들어 나이를 props로 받아 화면에 렌더링 하는 컴포넌트가 있다고 예를 들어보죠.

// components/Child.js

import React from 'react';

function Child({ name }){
	return <div>내 이름은 {name} 입니다. </div>
}

export default Child

Child 컴포넌트 입장에서는 부모 컴포넌트에서 nameprops 정보를 받기 전까지는 name 이 없는 상태죠. 그래서 자식 컴포넌트 입장에서는 name이 무엇인지 알 수 없습니다. 결과적으로 자식컴포넌트는 화면에 아무것도 표시해주지 못하게 됩니다. (이렇게요 내 이름은 "" 입니다. )

굉장히 어색하겠죠? 그래서 부모 컴포넌트에서 props를 받기전까지 임시로 사용 할 수 있는 props를 설정 할 수 있습니다. Child 컴포넌트에서 직접이요! 이후에 부모 컴포넌트에서 name props가 오게되면 설정된 defaultProps는 사라지고 내려 받은 props로 값이 바뀌게 됩니다.

defaultProps 지정하기

// components/Child.js

import React from 'react';

function Child({ name }){
	return <div>내 이름은 {name} 입니다. </div>
}

// 이렇게 설정합니다.
Child.defaultProps={
	name: '기본 이름'
}

export default Child

이렇게 defaultProps를 설정하면, 부모 컴포넌트로부터 아직 props 값을 받지 못했더라고 임시로 props의 값을 채울 수 있습니다. 그리고 부모 컴포넌트로부터 props가 오게되면 defaultProps 값은 진짜 props 값으로 변경됩니다. 아래 코드처럼도 할 수 있는데, 방법만 다를 뿐 모두 defaultProps를 설정하는 방법 입니다. 마치 함수의 default argument를 설정하는 것과 같죠?

import React from 'react';

// 구조 분해 할당 문법을 사용하면 이렇게도 할 수 있어요.
function Child({ name = '기본이름' }){
	return <div>내 이름은 {name} 입니다. </div>
}

export default Child

더 알아보면 좋은 키워드

  • object literal 이란 무엇인가?

  • default argument란 무엇인가?

profile
문제를 해결하고 가치를 제공합니다

0개의 댓글