컴포넌트에 데이터를 전달하는 방법
1. Props
Props : 부모 컴포넌트에서 자식 컴포넌트에게 어떤 값들에 이름을 붙여 전달하는 방식. 프로퍼티스의 줄임말.
- App.js
// import logo from './logo.svg';
// import './App.css';
import MyHeader from './MyHeader';
import Counter from './Counter';
function App() {
return (
<div>
<MyHeader/>
<Counter a={1} b={2} c={3} d={4} e={5} initialValue={5}/>
</div>
);
}
export default App;
- Counter.js
import React, { useState } from 'react';
const Counter = (props) => {
console.log(props); // 객체에 담겨서 온다.
const[count, setCount] = useState(props.initialValue); // 비구조화 할당 - 0 : 상태값, 1 : 상태값을 변화시키는 상태변화 함수, useState(초기값)
const onIncrease = () => {
setCount(count + 1);
}
const onDecrease = () => {
setCount(count - 1);
}
return(
<div>
<h2>{count}</h2>
<button onClick={onIncrease}>+</button>
<button onClick={onDecrease}>-</button>
</div>
)
}
export default Counter;
<Counter/> 에 직접 key와 value 값을 넘겨줄 수 있다. 하지만 가독성이 떨어지므로, 객체로 만들고 객체를 펼쳐서 전달하는 스프레드 연산자를 통해 보내준다.
- App.js
// import logo from './logo.svg';
// import './App.css';
import MyHeader from './MyHeader';
import Counter from './Counter';
function App() {
const counterProps = {
a: 1
, b: 2
, c: 3
, d: 4
, e: 5
, initialValue: 5
}
return (
<div>
<MyHeader/>
<Counter {...counterProps}/>
</div>
);
}
export default App;
- Counter.js
import React, { useState } from 'react';
const Counter = ({ initialValue }) => { // 비구조화 할당을 통해 매개변수로 전달되는 props 객체에서 initialValue 만 꺼내 쓴 것.
const[count, setCount] = useState(initialValue); // 비구조화 할당 - 0 : 상태값, 1 : 상태값을 변화시키는 상태변화 함수, useState(초기값)
const onIncrease = () => {
setCount(count + 1);
}
const onDecrease = () => {
setCount(count - 1);
}
return(
<div>
<h2>{count}</h2>
<button onClick={onIncrease}>+</button>
<button onClick={onDecrease}>-</button>
</div>
)
}
export default Counter;
만약 initialValue 내려주려다가 까먹고 안내려주면 undefined 이 전달된다. 이후 + 버튼을 누르면 undefined + 1 이 되어 숫자가 아니라는 NaN이 뜨게 된다.
- App.js
// import logo from './logo.svg';
// import './App.css';
import MyHeader from './MyHeader';
import Counter from './Counter';
function App() {
const counterProps = {
a: 1
, b: 2
, c: 3
, d: 4
, e: 5
//, initialValue: 5
}
return (
<div>
<MyHeader/>
<Counter {...counterProps}/>
</div>
);
}
export default App;
이런 오류를 방지하기 위해 defaultProps 사용하여 부모 컴포넌트가 값을 내려주지 않아도 자식 컴포넌트에서 기본값을 설정할 수 있다.
- Counter.js
import React, { useState } from 'react';
const Counter = ({ initialValue }) => { // 비구조화 할당을 통해 매개변수로 전달되는 props 객체에서 initialValue 만 꺼내 쓴 것.
console.log(initialValue);
const[count, setCount] = useState(initialValue); // 비구조화 할당 - 0 : 상태값, 1 : 상태값을 변화시키는 상태변화 함수, useState(초기값)
const onIncrease = () => {
setCount(count + 1);
}
const onDecrease = () => {
setCount(count - 1);
}
return(
<div>
<h2>{count}</h2>
<button onClick={onIncrease}>+</button>
<button onClick={onDecrease}>-</button>
</div>
)
}
Counter.defaultProps = {
initialValue: 0
}
export default Counter;
자식 컴포넌트에게 props로 동적인 데이터도 전달 가능하다. 즉 state 도 전달 가능하다.
- OddEvenResult.js
const OddEvenResult = ({ count }) => {
console.log(count);
return <>{count % 2 === 0 ? '짝수' : '홀수'}</>
}
export default OddEvenResult;
- Counter.js
import React, { useState } from 'react';
import OddEvenResult from './OddEvenResult';
const Counter = ({ initialValue }) => { // 비구조화 할당을 통해 매개변수로 전달되는 props 객체에서 initialValue 만 꺼내 쓴 것.
const[count, setCount] = useState(initialValue); // 비구조화 할당 - 0 : 상태값, 1 : 상태값을 변화시키는 상태변화 함수, useState(초기값)
const onIncrease = () => {
setCount(count + 1);
}
const onDecrease = () => {
setCount(count - 1);
}
return(
<div>
<h2>{count}</h2>
<button onClick={onIncrease}>+</button>
<button onClick={onDecrease}>-</button>
<OddEvenResult count={count}/>
</div>
)
}
Counter.defaultProps = {
initialValue: 0
}
export default Counter;
리액트의 컴포넌트는 부모 컴포넌트가 내려주는 props 가 변경되면 리랜더가 일어난다. 부모 컴포넌트 state 가 바뀌면 자식 컴포넌트도 리랜더가 된다.
정리하자면 첫 번째로, 리액트의 컴포넌트는 본인이 가진 state 가 바뀔 때 마다 리랜더가 되고, 두 번째로, 부모 컴포넌트로부터 내려오는 props 가 바뀔 때 마다 리랜더가 되고, 세 번째로, 부모 컴포넌트가 리랜더가 되면 자식 컴포넌트도 리랜더가 된다.
컴포넌트 자체를 props 로 전달하여 컴포넌트를 컴포넌트로 감싸본다.
- Container.js
const Container = ({ children }) => {
console.log(children);
return (
<div style={{ margin: 20, padding: 20, border: "1px solid gray" }}>
{children}
</div>
);
};
export default Container;
- App.js
// import logo from './logo.svg';
// import './App.css';
import MyHeader from './MyHeader';
import Counter from './Counter';
import Container from './Container';
function App() {
const counterProps = {
a: 1
, b: 2
, c: 3
, d: 4
, e: 5
//, initialValue: 5
}
return (
<Container>
<div>
<MyHeader/>
<Counter {...counterProps}/>
</div>
</Container>
);
}
export default App;
컴포넌트 사이에 JSX 요소들을 배치하면, 자식 요소들 자체가 props 으로 전달된다.
이렇게 리액트의 props 기능은 컴포넌트를 다른 컴포넌트의 props 로 전달할 수 있다.
(state 와 props 는 이 두 개 자체로 리액트 자체라고 생각해도 무방할 정도로 중요함)
참고강의 : https://www.inflearn.com/course/%ED%95%9C%EC%9E%85-%EB%A6%AC%EC%95%A1%ED%8A%B8#
한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지 강의 - 인프런
개념부터 독특한 프로젝트까지 함께 다뤄보며 자바스크립트와 리액트를 이 강의로 한 번에 끝내요. 학습은 짧게, 응용은 길게 17시간 분량의 All-in-one 강의!, 리액트, 한 강의로 끝장낼 수 있어요.
www.inflearn.com
'강의 실습 > 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지' 카테고리의 다른 글
React에서 사용자 입력 처리하기 (2) | 2024.01.13 |
---|---|
프로젝트 소개 (0) | 2024.01.11 |
State (2) | 2024.01.10 |
JSX (0) | 2024.01.09 |
Create React App (4) | 2024.01.08 |
댓글