👉🏻 State 끌어올리기
종종 동일한 데이터(State)에 대한 변경사항을 여러 컴포넌트에 반영해야 할 필요가 있습니다. 이럴 때는 가장 가까운 공통 조상으로 state를 끌어올리는 것이 좋습니다. 또한, 대안적인 방안으로 Redux
나 Recoil
같은 전역 상태 관리 라이브러리를 통하여 보완할 수 있습니다.
리액트 공식 문서를 통하여 Hooks로 전환하여 물의 끓는 여부를 추정하는 온도 계산기를 실습하며 정리한 부분이며 자세한 사항은 공식문서를 참조바랍니다. React 애플리케이션 안에서 변경이 일어나는 데이터에 대해서는 “진리의 원천(source of truth)“
을 하나만 두어야 합니다. 다른 컴포넌트 간에 존재하는 state를 동기화시키려고 노력하는 대신 하향식 데이터 흐름
에 기대는 걸 추천합니다.
state를 끌어올리는 작업은 양방향 바인딩 접근 방식보다 더 많은 “보일러 플레이트” 코드를 유발하지만, 버그를 찾고 격리하기 더 쉽게 만든다는 장점이 있습니다. UI에서 무언가 잘못된 부분이 있을 경우, React Developer Tools를 이용하여 props를 검사하고 state를 갱신할 책임이 있는 컴포넌트를 찾을 때까지 트리를 따라 탐색면 버그를 추적할 수 있습니다.
import React, { useState } from 'react';
import ReactDOM from "react-dom";
const scaleNames = {
c: 'Celsius',
f: 'Fahrenheit'
};
function toCelsius(fahrenheit) {
return (fahrenheit - 32) * 5 / 9;
}
// convert에 들어갈 함수
function toFahrenheit(celsius) {
return (celsius * 9 / 5) + 32;
}
// convert에 들어갈 함수
function tryConvert(temperature, convert) {
const input = parseFloat(temperature);
if (Number.isNaN(input)) {
return '';
}
const output = convert(input);
const rounded = Math.round(output * 1000) / 1000;
return rounded.toString();
}
// 계산값을 소수 3자리 반올림
function BoilingVerdict(props) {
if (props.celsius >= 100) {
return <p>The water would boil.</p>;
}
return <p>The water would not boil.</p>;
}
// 섭씨온도 prop를 받아서 온도가 물이 끓는지 여부를 출력
function TemperatureInput ({onTemperatureChange, temperature, scale}) {
const handleChange = (e) => {
onTemperatureChange(e.target.value);
}
return (
<fieldset>
<legend>Enter temperature in {scaleNames[scale]}:</legend>
<input value={temperature}
onChange={handleChange} />
</fieldset>
);
}
function Calculator () {
const [temperature, setTemperature] = useState('');
const [scale, setScale] = useState('c');
// 온도를 입력할 수 있는 <input>을 렌더링하고 그 값을 저장
const handleCelsiusChange = (temperature) => {
setScale('c');
setTemperature(temperature);
}
// onTemperatureChange props 호출시 input 필드에 따라 해당 함수 호출
const handleFahrenheitChange = (temperature) => {
setScale('f');
setTemperature(temperature);
}
// onTemperatureChange props 호출시 input 필드에 따라 해당 함수 호출
const celsius = scale === 'f' ? tryConvert(temperature, toCelsius) : temperature;
const fahrenheit = scale === 'c' ? tryConvert(temperature, toFahrenheit) : temperature;
// 어떤 입력 필드를 수정하느냐에 따라서 Calculator의 두 메서드 중 하나가 호출
return (
<div>
// 분리된 두 개의 온도 입력 필드
<TemperatureInput
scale="c"
temperature={celsius}
onTemperatureChange={handleCelsiusChange} />
<TemperatureInput
scale="f"
temperature={fahrenheit}
onTemperatureChange={handleFahrenheitChange} />
// TemperatureInput이 개별적으로 가지고 있던 지역 state를 Calculator로 onTemperatureChange를 통한 함수 호출을 통해 옮김
<BoilingVerdict
celsius={parseFloat(celsius)} />
</div>
);
}
ReactDOM.render(
<Calculator />,
document.getElementById('root')
);
👉🏻 예제
보일러 플레이트
Redux, Recoil, Context
lifting process