[React] # 9 State 끌어올리기

simoniful·2021년 7월 8일
0

React

목록 보기
9/13
post-thumbnail

실습

👉🏻 State 끌어올리기

종종 동일한 데이터(State)에 대한 변경사항을 여러 컴포넌트에 반영해야 할 필요가 있습니다. 이럴 때는 가장 가까운 공통 조상으로 state를 끌어올리는 것이 좋습니다. 또한, 대안적인 방안으로 ReduxRecoil 같은 전역 상태 관리 라이브러리를 통하여 보완할 수 있습니다.

리액트 공식 문서를 통하여 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

profile
소신있게 정진합니다.

0개의 댓글