섭씨 (Celsius) 온도를 입력하면 해당하는 화씨 (Fahreheit) 온도와 켈빈 (Kelvin) 온도가 다른 두 컴포넌트에 즉시 반영되는 온도 변환기를 예시로 생각해보자.
입력 컴포넌트가 자신의 상태를 다른 컴포넌트와 공유하려면, 상태를 필요로 하는 컴포넌트와 가장 가까운 공통 조상 컴포넌트로 끌어올려야 한다.
function Input({ value, handleChange }) {
return <input value={value} onChange={(e) => handleChange(e.target.value)} />;
}
function Kelvin({ value = 0 }) {
return <div className='temp'>{value + 273.15} K</div>;
}
function Fahrenheit({ value = 0 }) {
return <div className='temp'>{(value * 9) / 5 + 32} °F</div>;
}
export default function App() {
const [value, setValue] = useState('');
return (
<div className='App'>
<h1>Temperature Converter</h1>
<Input value={value} handleChange={setValue} />
<Kelvin value={value} />
<Fahrenheit value={value} />
</div>
);
}
형제 컴포넌트 간에 상태를 공유해야 하는 경우
redux 나 Context API 와 같은 전역 상태관리 대신 이 패턴을 사용하여
"가장 가까운 공통 조상 컴포넌트로 끌어올린다."
많은 자식 컴포넌트를 처리하는 큰 규모의 Application 에서는 상태 끌어올리기가 복잡해질 수 있다.
각 상태 변경 시 데이터를 사용하지 않는 자식 컴포넌트까지 모두 리렌더링 될 수 있어 성능에 악영향을 술 수 있다.
-> 이 경우 렌더링 Props 패턴을 사용하면 이러한 문제를 해결할 수 있다.
Input 컴포넌트가 렌더링 props를 받을 수 있도록 변경해보자!
function Kelvin({ value = 0 }) {
return <div className='temp'>{value + 273.15} K</div>;
}
function Fahrenheit({ value = 0 }) {
return <div className='temp'>{(value * 9) / 5 + 32} °F</div>;
}
function Input(props) {
const [value, setValue] = useState('');
return (
<>
<input
type='text'
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder='Temp in °C'
/>
{props.render(value)}
</>
);
}
export default function App() {
return (
<div className='App'>
<h1>Temperature Converter</h1>
<Input
render={(value) => (
<>
<Kelvin value={value} />
<Fahrenheit value={value} />
</>
)}
/>
</div>
);
}