Props를 통한 부모 → 자식 데이터 전달
React에서 컴포넌트는 기본적으로 독립적인 단위이므로 외부로부터 데이터를 받기 위해서는 props를 사용해야 합니다. props는 컴포넌트에 전달되는 읽기 전용 입력값입니다.
// 부모 컴포넌트에서 속성으로 데이터 전달
<UserProfile name="김민수" age={28} isActive />
// 함수형 컴포넌트: 매개변수로 props 수신
function UserProfile(props) {
return (
<div>
이름: {props.name}, 나이: {props.age}, 상태: {props.isActive ? '활성화' : '비활성화'}
</div>
);
}
// 클래스형 컴포넌트: this.props로 접근
class UserProfile extends React.Component {
render() {
return <div>반갑습니다, {this.props.name}님!</div>;
}
}
Props 특징
- 임의의 자료형 전달 가능 (문자열, 숫자, 배열, 객체, 함수, JSX 등)
- 읽기 전용 – 수정 불가능
- 클래스 컴포넌트 생성자에서
super(props)호출 필수
class UserProfile extends React.Component {
constructor(props) {
super(props); // 반드시 props 전달
console.log(this.props.name); // 생성자 내에서도 접근 가능
}
render() {
return <div>{this.props.name}</div>;
}
}
자식 → 부모 데이터 전달: 콜백 함수 활용
자식 컴포넌트가 부모에게 데이터를 전달하려면, 부모가 콜백 함수를 props로 전달하고, 자식이 이를 호출하는 방식을 사용합니다.
class Parent extends React.Component {
handleChildData = (data) => {
console.log('자식으로부터 받은 데이터:', data);
};
render() {
return <Child onSubmit={this.handleChildData} />;
}
}
class Child extends React.Component {
state = { message: 'Hello from child' };
handleClick = () => {
this.props.onSubmit(this.state.message);
};
render() {
return <button onClick={this.handleClick}>데이터 전송</button>;
}
}
형제 컴포넌트 간 통신: 상태 승격 (Lifting State Up)
두 자식 컴포넌트가 같은 데이터를 공유해야 할 경우, 공통 부모 컴포넌트에 상태를 두고 각각 props로 전달합니다.
class SharedCounter extends React.Component {
state = { count: 0 };
increment = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<Display count={this.state.count} />
<IncrementButton onInc={this.increment} />
</div>
);
}
}
const Display = ({ count }) => <h2>현재 값: {count}</h2>;
const IncrementButton = ({ onInc }) => <button onClick={onInc}>+1</button>;
깊은 중첩 컴포넌트 간 데이터 전달: Context API
여러 계층을 거쳐 props를 전달하는 번거로움을 줄이기 위해 Context를 사용할 수 있습니다. 주로 테마, 언어 설정 등 전역 상태 관리에 적합합니다.
// Context 생성
const ThemeContext = React.createContext('light');
// Provider로 감싸서 데이터 제공
class App extends React.Component {
render() {
return (
<ThemeContext.Provider value="dark">
<NavigationBar />
</ThemeContext.Provider>
);
}
}
// Consumer 또는 useContext로 데이터 사용
const NavigationBar = () => (
<ThemeContext.Consumer>
{theme => <nav className={theme}>내비게이션 바</nav>}
</ThemeContext.Consumer>
);
컴포넌트 자식 요소 다루기: children Prop
children은 특수한 prop으로, 태그 사이에 포함된 내용을 나타냅니다. 이는 문자열, 엘리먼트, 컴포넌트, 함수까지 포함할 수 있어 유연한 구조를 가능하게 합니다.
function Card({ children }) {
return <div className="card" style={{ padding: '20px', border: '1px solid #ccc' }}>{children}</div>;
}
// 사용 예시
<Card>
<h3>카드 제목</h3>
<p>이것은 카드 내용입니다.</p>
</Card>
Props 검증: PropTypes
외부에서 전달받는 props의 형식을 검사하여 실수를 조기에 발견할 수 있습니다. 개발 환경에서만 동작하며, 코드 안정성을 높여줍니다.
import PropTypes from 'prop-types';
function UserCard({ name, age, avatar, tags }) {
return (
<div>
<img src={avatar} alt="프로필" />
<h4>{name} ({age})</h4>
<ul>
{tags.map(tag => <li key={tag}>{tag}</li>)}
</ul>
</div>
);
}
UserCard.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number,
avatar: PropTypes.string,
tags: PropTypes.arrayOf(PropTypes.string)
};
UserCard.defaultProps = {
age: 20,
tags: []
};
Props 기본값 설정
특정 props가 전달되지 않았을 때 사용할 기본값을 지정할 수 있습니다. 재사용 가능한 컴포넌트 설계에 매우 유용합니다.
function Pagination({ pageSize, onPageChange }) {
return (
<div>
페이지 크기: {pageSize}
<button onClick={() => onPageChange(1)}>다음 페이지</button>
</div>
);
}
Pagination.defaultProps = {
pageSize: 10,
onPageChange: () => {}
};