React, 섭씨온도와 화씨온도 표시하기, Shared State

2024. 12. 4. 11:22웹 개발

TemperatureInput.jsx

// state 는 제거되었고, 오로지 상위 컴포넌트의 props 만 사용됨
const scaleNames = {
    c: "섭씨",
    f: "화씨",
};

function TemperatureInput(props) {

    const handleChange = (event) => {
        props.onTemperatureChange(event.target.value); // 2. 상위 컴포넌트로 변경된 값을 전달
    };

    return (
        <fieldset>
            <legend>
                온도를 입력해주세요 (단위: {scaleNames[props.scale]})
            </legend>
            <input
                value={props.temperature} // 1. 온도값을 state 가 아닌 props 에서 가져옴
                onChange={handleChange}
            />
        </fieldset>
    );
}

export default TemperatureInput; // 컴포넌트를 외부에서 사용할 수 있도록 내보내기

 

Calculator.jsx

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

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();
}

function BoilingVerdict({ celsius }) { // 섭씨온도를 props로 받음
    if (celsius >= 100) {
        return <p>물이 끓습니다.</p>;
    }
    return <p>물이 끓지 않습니다.</p>;
}

function Calculator() {

    const [temperature, setTemperature] = useState("");
    const [scale, setScale] = useState("c");

    const handleCelsiusChange = (temperature) => {
        setTemperature(temperature);
        setScale("c");
    };

    const handleFahrenheitChange = (temperature) => {
        setTemperature(temperature);
        setScale("f");
    };

    const celsius = scale === "f" ? tryConvert(temperature, toCelsius) : temperature;
    const fahrenheit = scale === "c" ? tryConvert(temperature, toFahrenheit) : temperature;

    return (
        <div>
            <TemperatureInput
                scale="c" // props 로 하위 컴포넌트에 전달 (단위: 섭씨)
                temperature={celsius}
                onTemperatureChange={handleCelsiusChange} // 하위 컴포넌트에서 전달받아 호출
            />
            <TemperatureInput
                scale="f" // props 로 하위 컴포넌트에 전달 (단위: 화씨)
                temperature={fahrenheit} // props 로 하위 컴포넌트에 전달
                onTemperatureChange={handleFahrenheitChange}
            />
            <BoilingVerdict celsius={parseFloat(celsius)} />
        </div>
    );
}

export default Calculator;

 

index.js

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import PlayGround from "./chapter_00/PlayGround";

import Calculator from "./chapter_12/Calculator";

const root = ReactDOM.createRoot(document.getElementById("root"));

root.render(
    <React.StrictMode>
        <Calculator />
    </React.StrictMode>
);

reportWebVitals();

// https://github.com/soaple/first-met-react-practice-v18/tree/master/src

 

결과

 

출처

https://www.inflearn.com/course/처음-만난-리액트

https://github.com/soaple/first-met-react-practice-v18/tree/master/src

 

https://stackblitz.com/edit/react-basecamp-v6stmp?embed=1&file=index.html