data life

[React] State 끌어올리기 본문

Front-end/React

[React] State 끌어올리기

주술회전목마 2023. 3. 29. 06:01

state 끌어올리기

function A(){
   return(
      <>
        <B />
        <C />
      </>
   );
}

위와 같은 구조의 컴포넌트들이 존재한다고 가정해보자.

만일 C컴포넌트에서 B컴포넌트가 가진 state가 필요하다 할 때의 상황이라면 어떻게 하는 것이 좋은가?

B컴포넌트 C컴포넌트가 가지고 있는 state A컴포넌트로 끌어올려 사용하면 편리하지 않을까?

이때, 바로 props를 이용하여 state를 주고받을 수 있다.

 

 

섭씨 기준 100도 이상 또는 화씨 기준 212 이상이면 끓는 물, 아니면 끓지 않는 물이라는 메세지를 보여주도록 구현한 화면이다.

이때, 섭씨와 화씨는 서로 다른 state를 갖도록 구현하도록 함.

 

동일한 기능은 다음과 같다.

  • input에 숫자 입력
  • 특정 기준치에 이상이면 끓는 물, 아니면 끓지 않는 물이라는 메세지를 보여줌
/**Calculator.js**/
import React from "react";
import BoilingVerdict from "./BoilingVerdict";
import TemperatureInput from "./TemperatureInput";

export default function Calculator() {
  return (
    <>
      <TemperatureInput scale={"c"} />
      <TemperatureInput scale={"f"} />
    </>
  );
}
/**BoilingVerdict.js**/

export default function BoilingVerdict(props) {
  // 섭씨
  if (props.scale === "c") {
    if (props.temperature >= 100) {
      return <p>The water would boil.</p>;
    }
    return <p>The water would not boil.</p>;
  }

  // 화씨
  if (props.temperature >= 212) {
    return <p>The water would boil.</p>;
  }
  return <p>The water would not boil.</p>;
}
/**TemperatureInput.js**/
import React, { useState } from "react";
import BoilingVerdict from "./BoilingVerdict";

const scaleNames = {
  c: "Celsius", // 섭씨
  f: "Fahrenheit", // 화씨
};

export default function TemperatureInput(props) {
  const [temperature, setTemperature] = useState(0);

  function handleChange(e) {
    setTemperature(e.target.value);
  }

  const scale = scaleNames[props.scale];

  return (
    <fieldset>
      <legend>Enter temperature in {scale}:</legend>
      <input value={temperature} onChange={handleChange} />
      <BoilingVerdict
        scale={props.scale}
        temperature={parseFloat(temperature)}
      />
    </fieldset>
  );
}

 

추가 기능 구현

  • 섭씨 온도 <-> 화씨 온도

섭씨 / 화씨 중 어느 한 곳에 온도값을 입력하면 단위 변환하여 서로 값을 나타내주도록 기능을 부여해주도록 함

 

/**Calculator**/
const [state, setState] = useState({
     scale : "c",
     temperature : 0,
});

객체(obj)를 받아 어디서 수정했는지, 값(온도)는 무엇인지 알려주는 온도변화 함수를 만들어준다.

const handleTemperatureChange = (obj) => {
   // 어디서수정했는지, 값(온도)는 무엇인지
   //obj.scale, obj.temperature
   setState({...state, scale:obj.scale, temperature : obj.temperature})
}

 

단위 변환 함수

  • toCelsius
  • toFahrenheit
  //섭씨 변환
  function toCelsius(fahrenheit){
     return ((fahrenheit - 32) * 5) / 9;
  }
  
  //화씨 변환
  function toFahrenheit(celsius){
    return (celsius * 9) / 5 + 32;
  }
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();
}

이후, state에서 scale과 temperature 변수를 가져와

삼항연산자를 이용하여 각 변수에 해당하는 값이 아닐경우, tryConvert를 이용하여 값을 반환하도록 해준다.

const {scale, temperature} = state;

const celsius = scale === "f" ? tryConvert(tempertaure, toCelsius) : temperature
const fahrenheit = scale === "c" ? tryConvert(temperature, toFahrenheit) : temperature
return (
   <>
     <TemperatureInput scale={"c"} temperature={celsius} onTemperatureChange={handleTemperatureChange} />
     <TemperatureInput scale={"f"} temperature={fahrenheit} onTemperatureChange={handleTemperatureChange}/>
   </>
)

마찬가지로, state를 받는 Temperature.js에서도 변경하면 다음과 같다.

/**TemperatureInput.js**/
import React, { useState } from "react";
import BoilingVerdict from "./BoilingVerdict";

const scaleNames = {
  c: "Celsius", // 섭씨
  f: "Fahrenheit", // 화씨
};

export default function TemperatureInput(props) {
  //const [temperature, setTemperature] = useState(0);

  function handleChange(e) {
    //setTemperature(e.target.value);
    props.onTemperatureChange({scale:props.scale, temperature:e.target.value});
  }

  const scale = scaleNames[props.scale];

  return (
    <fieldset>
      <legend>Enter temperature in {scale}:</legend>
      <input value={props.temperature} onChange={handleChange} />
      <BoilingVerdict
        scale={props.scale}
        temperature={parseFloat(props.temperature)}
      />
    </fieldset>
  );
}

각각 컴포넌트에 존재하던 state를 Calculator 컴포넌트, 즉 상위 컴포넌에서 관리하도록 도와주었다.

 

 

'Front-end > React' 카테고리의 다른 글

[React] Hook 함수 중 useEffect()  (0) 2023.03.29
[React] 생명주기 (Life-Cycle)  (0) 2023.03.29
[React] State의 비동기적 업데이트  (0) 2023.03.29
[React] State  (0) 2023.03.29
[React] 라이브러리 vs 프레임워크  (0) 2023.03.24