✨ 부모 -> 자식 데이터 전달 메커니즘인 props
부모 컴포넌트가 자식 컴포넌트에게 물려준 데이터
즉 컴포넌트 간의 정보 교류 방법입니다.
아래 2가지 내용을 기억해주시면 되는데
1. props
는 반드시 위에서 아래 방향으로 흐른다 (단방향)
2. props
는 반드시 읽기 전용으로 취급하며, 변경하지 않는다.
컴포넌트 간의 정보를 교류할 때 Props
를 사용한다.
다른 컴포넌트는 생략하고, Mother
를 보면
Mother
컴포넌트가 가진 정보를 Child
에게 주고 싶으면 아래와 같이 작성하면 됩니다.
motherName
이라는 이름으로 name
값을Child
컴포넌트에 전달해준 것인데,
이 과정을 Props
로 정보를 전달했다 라고 할 수 있습니다.
// src/App.jsx
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;
// 자식은 어떻게 받아야 할까?
function Child(props){
console.log(props) // 이게 바로 props다.
return <div>연결 성공</div>
}
// 컴포넌트의 인자에서 props의 값을 받을 수 있다.
저렇게 props
를 전달받으면 어떤 형태로 받아지냐면
console
에 확인하면 객체 형태로 전달받는 걸 확인할 수 있다.
props
란 결국 부모 컴포넌트가 자식에게 넘겨준 데이터들의 묶음이라고 할 수 있다.
리액트에서는 Props
를 통해 부모 컴포넌트로부터 자식 컴포넌트에 데이터를 넘겨줄 수 있다.
Mother
로 전달받은 motherName
을 화면에 렌더링 하려면?
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;
props
는 object literal
형태여서 {props.motherName}
로 꺼내 사용할 수 있습니다.
object literal
의 key
가 motherName
인 이유는 우리가 Child
로 보낼 때
motherName={name}
로 보내준 것이기 때문이다.
object literal 란 {key:"value"} 데이터 형태를 의미합니다.
그런데 JSX에서는 HTML만 사용할 수 있는데 자바스크립트 코드가 왜 존재하냐면
JSX에서도 {}
중괄호를 사용할 수 있기 때문입니다.
혹시 자식 컴포넌트에서 부모 컴포넌트로 props를 전달 할 수 없나?
자식 컴포넌트에서는 부모 컴포넌트로 props를 전달할 수 없습니다.
오직 부모컴포넌트에서 자식 컴포넌트로만 props를 전달할 수 있습니다
왜? 단방향이라는 걸 잊어서는 안됩니다.
부모 - 자식 컴포넌트간 데이터 전달이 이루어지는 방법이 props
인데
부모 - 자식 - 자식의 자식 - 자식의 자식의 자식... 이 데이터를 받기 위해
3번이나 데이터를 내려주게 되는데,
이게 바로 prop drilling
, props
가 아래로 뚫고 내려가는 의미입니다.
아래는 prop drilling
의 예시 코드이다.
export default function App() {
return (
<div className="App">
<FirstComponent content="Who needs me?" />
</div>
);
}
function FirstComponent({ content }) {
return (
<div>
<h3>I am the first component</h3>;
<SecondComponent content={content} />|
</div>
);
}
function SecondComponent({ content }) {
return (
<div>
<h3>I am the second component</h3>;
<ThirdComponent content={content} />
</div>
);
}
function ThirdComponent({ content }) {
return (
<div>
<h3>I am the third component</h3>;
<ComponentNeedingProps content={content} />
</div>
);
}
function ComponentNeedingProps({ content }) {
return <h3>{content}</h3>;
}
✨ props 중 children의 개념과 사용 방법
자식 컴포넌트로 정보를 전달하는 또 다른 방법인데
이 친구도 props
의 일종이다!
우리는 부모 컴포넌트에서 정보를 보낼 때, 자식 컴포넌트에서 그 정보를 사용하고 싶다면
props
를 통해 정보를 받아와야 했습니다.
그러나 children props
를 활용해 자식 컴포넌트에서 정보를 받는 방식이
기존과 동일한데 대신 children
으로 이름이 정해져 있기 때문에 children props
입니다.
아래의 예시를 보면 이해할 수 있다.
import React from "react";
function User(props) {
return <div>{props.children}</div>;
}
function App() {
return <User>안녕하세요</User>;
}
export default App;
Layout
컴포넌트를 만들 때 주로 사용하는데...
Layout
컴포넌트 안에는 header
라는 컴포넌트가 존재하고, header
아래에
{props.children}
를 통해 props
를 받아 렌더링 하고 있습니다.
즉 Layout
컴포넌트가 쓰여지는 모든 곳에서 안에 정보를 가져올 수 있는 것이다.
// src/About.jsx
import React from "react";
import Layout from "./components/Layout";
function App() {
return (
<Layout>
<div>여긴 App의 컨텐츠가 들어갑니다.</div>
</Layout>
);
}
export default App;
위의 코드를 통해 Layout
에 있는 header
가 보여지게 되고,
태그안의 문장이 Layout
의 props
로 전달되고 있는 것입니다.
결과적으로 header
컴포넌트를 Layout
컴포넌트에서 한번만 작성하면
여러 페이지에서 모두 보여지게 할 수 있는 것 입니다.
즉 Layout
의 header
와 About
의 내용이 동시에 보여지게 됩니다.
✨ props를 추출하여 활용하는 여러 방법이 있습니다.
우리가 지금까지 자식 컴포넌트에서 props
를 받을 때 이런 형태였습니다.
function Todo(props){
return <div>{props.todo}</div>
}
문제는 없지만 todo라는 props
를 사용하는 모든 곳에props.
를 붙여줘야 한다.
이를 단축하는 방법이 있는데, 바로 자바스크립트의 구조 분해 할당을 이용하는 것입니다.
props
는 object literal
형태의 데이터여서 우리는 구조 분해 할당을 이용할 수 있습니다.
function Todo({ title }){
return <div>{title}</div>
}
위처럼 훨씬 간결하게 작성할 수 있습니다.
그러나 만약 여러개의 props
를 받는다면 {}
안에 여러개의 props
를 그대로 사용하면 됩니다.
앞으로의 모든 공부에서 구조 분해 할당을 다양한 형태로 볼 수 있을 것이다.
function Todo({ title, body, isDone, id }){
return <div>{title}</div>
}
부모 컴포넌트에서 자식 컴포넌트로 정보를 전달할 때 사용하는데,
특정 props
가 부모 컴포넌트로부터 전달되지 않을 수도 있습니다.
이런 경우 자식 컴포넌트에서 해당 props
의 기본값을 설정해 줄 필요가 있는데
이를 위해 리엑트에서 default arguments
방식을 활용할 수 있습니다.
Default Arguments
는 함수의 매개변수에서 기본 값을 설정하는 자바스크립트의 표준 기능입니다.
리액트의 함수형 컴포넌트에서는 이 기능을 활용하여 props의 기본값을 쉽게 정의할 수 있습니다.
컴포넌트가 부모로부터 특정 props를 받지 못했을 경우에도 에러 없이 기본 값을 사용하여 컴포넌트를 렌더링할 수 있게 해줍니다.
예를 들어, 어떤 컴포넌트가 사용자의 이름을 출력하는 기능을 가지고 있지만,
부모 컴포넌트가 이름을 제공하지 않는 경우가 있다고 가정한다면
function Welcome({ name = "Guest" }) {
return <h1>Welcome, {name}!</h1>;
}
위 코드에서 name = "Guest"
는 name
prop이 전달되지 않았을 때 "Guest"라는
기본 값을 사용하도록 설정을 합니다.
이렇게 설정함으로써, 부모 컴포넌트에서 name
prop을 제공하지 않아도
Welcome 컴포넌트는 Welcome, Guest 라는 문구를 표시할 수 있습니다.