React

React로 단위 변환기 만들기 💻

yunieyunie 2023. 5. 1. 22:13

1. minutes -> hours

먼저 분을 시간으로 바꿔주는 코드를 작성해보자.

<body>
    <div id="root"></div>
  </body>

  <script type="text/babel">
   
    function App(){
      const [minutes, setMinutes] = React.useState();

      const onChange = (event) => {
        setMinutes(event.target.value);
      };

      const reset = () => {
        setMinutes(0);
      };

      return(
        <div>
          <div>
            <label htmlFor="minutes">minutes</label>
            <input value={minutes} id="minutes" placeholder="minutes" type="number" onChange={onChange} />
          </div>
         
          <div>
            <label htmlFor="minutes">hours</label>
            <input value={minutes/60} id="hours" placeholder="hours" type="number" disabled />
          </div>

          <button onClick={reset}>Reset</button>
        </div>
      );
    }

    const root = document.getElementById("root");
    ReactDOM.render(<App />, root);
  </script>

 

먼저 label는 클릭하면 해당 input에 입력할 수 있도록 하는 태그다.

input의 id 값을 htmlFor 에 넣어주면 되는데 여기서 기억할 점은 for가 아니라 htmlFor라는 것이다.

 

onChange 함수는 데이터를 업데이트 해주는 역할을 한다.

이벤트가 일어났을 때, 즉 input에 사용자가 숫자를 입력하면 onChange 함수가 실행되는데 이 함수는 사용자가 입력한 숫자인 event.target.value 값을 state (minutes)에 넣는다.

그래서 minutes에 숫자가 입력되면 hours 칸에서는 이 숫자를 60으로 나눈 값을 보여준다.

이 때 hours의 input에는 onChange를 넣지 않았고 disabled가 있기에 숫자를 입력할 수 없게 된다.

 

reset 기능은 버튼을 눌렀을 때 state를 0으로 만들어 주는 것이다.

 

 

2. minutes <-> hours

이번엔 시간을 분으로도 바꿔보는 기능을 추가해보자. 

먼저 state이름을 minutes에서 amount로 바꾸자.

<body>
    <div id="root"></div>
  </body>

  <script type="text/babel">
   
    function App(){
      const [amount, setAmount] = React.useState();
      const [inverted, setInverted] = React.useState(false);

      const onChange = (event) => {
        setAmount(event.target.value);
      };

      const reset = () => {
        setAmount(0);
      };

      const onInvert = () => {
        reset();
        setInverted((cur) => !cur);
      };

      return(
        <div>
          <h1>Unit Converter</h1>
          <div>
            <label htmlFor="minutes">minutes</label>
            <input value={inverted ? amount*60 : amount} id="minutes" placeholder="minutes" type="number" onChange={onChange} disabled={inverted}
/>
          </div>
         
          <div>
            <label htmlFor="minutes">hours</label>
            <input value={inverted ? amount : amount/60} id="hours" placeholder="hours" type="number" onChange={onChange} disabled={!inverted}
/>
          </div>

          <button onClick={reset}>Reset</button>
          <button onClick={onInvert}>{inverted ? "minutes -> hours" : "hours -> minutes"}</button>
        </div>
      );
    }

    const root = document.getElementById("root");
    ReactDOM.render(<App />, root);
  </script>

먼저 hours input에도 onChange를 추가한다. hours에도 숫자를 입력하기 위함이다.

 

그리고 새로운 state를 하나 만드는데 default 값은 false로 넣어준다.

바꿔주는 버튼을 클릭하면 onInvert 함수가 실행되는데 이는 먼저 input 값을 0으로 만드는 reset 함수를 먼저 실행한 후, state값이 false면 true로, true면 false로 바꿔준다.

 

minutes input에 disabled는 inverted, hours input에 disabled 는 ! inverted를 입력하자.

minutes는 inverted가 true라면 disabled가 되는 것이고 hours는 inverted가 false라면 disabled 되는 것이다.

 

minutes input의 value는 inverted가 true라면 값이 amount 곱하기 60이고, hours input의 value는 inverted가 false일 때 amount 나누기 60을 한 값이 된다.

 

 

 

굳이 Inverted 버튼을 만들고 싶지 않다면 다음과 같이 해볼 수도 있다.

id가 minutes인 input 에서 입력할 경우와 hours에서 입력할 경우로 나눠주는 것이다.

<body>
    <div id="root"></div>
  </body>

  <script type="text/babel">
    const root = document.getElementById("root");

    function App (){
      const [amount, setAmount] = React.useState();
      const [hours, setHours] = React.useState();

      const onChange = (event) => {
        if (event.target.id === "minutes") {
          setAmount(event.target.value);
          setHours(event.target.value / 60);
          } else {
            setAmount(event.target.value * 60);
            setHours(event.target.value);
          }
      }

      const reset = () => {
        setAmount(0);
        setHours(0);
      };

      return(
        <div>
          <h1>Minutes and Hours converter</h1>
          <div>
            <label htmlFor="minutes">minutes</label>
            <input value={amount} id="minutes" placeholder="minutes" onChange={onChange} type="number"/>
          </div>
         
          <div>
            <label htmlFor="hours">hours</label>
            <input value={hours} id="hours" placeholder="hours" onChange={onChange} type="number" />
          </div>

          <button onClick={reset}>reset</button>
        </div>
      );
    }

    ReactDOM.render(<App />, root);
  </script>

 

 

3. 여러 단위 변환 기능 추가

이번엔 cm를 inch로, km를 mile로 바꾸는 기능을 추가해보기 위해 지금까지의 코드를 새로운 컴포넌트에 넣자.

MinutesToHours라는 함수를 만들고 h1 부분만 빼고 복붙하자.

그리고 원하는 변환 기능을 선택할 수 있도록 해보자.

 

<body>
    <div id="root"></div>
  </body>

  <script type="text/babel">
   
    function MinutesToHours(){
      const [amount, setAmount] = React.useState();
      const [inverted, setInverted] = React.useState(false);

      const onChange = (event) => {
        setAmount(event.target.value);
      };

      const reset = () => {
        setAmount(0);
      };

      const onInvert = () => {
        reset();
        setInverted((cur) => !cur);
      };

      return(
        <div>
          <div>
            <label htmlFor="minutes">minutes</label>
            <input value={inverted ? amount*60 : amount} id="minutes" placeholder="minutes" type="number" onChange={onChange} disabled={inverted}/>
          </div>
         
          <div>
            <label htmlFor="minutes">hours</label>
            <input value={inverted ? amount : amount/60} id="hours" placeholder="hours" type="number" onChange={onChange} disabled={!inverted} />
          </div>

          <button onClick={reset}>Reset</button>
          <button onClick={onInvert}>{inverted ? "minutes -> hours" : "hours -> minutes"}</button>
        </div>
      );
    }
 
    function CmtoInches(){
      const [amount, setAmount] = React.useState();
      const [inverted, setInverted] = React.useState(false);

      const onChange = (event) => {
        setAmount(event.target.value);
      }

      const reset = () => {
        setAmount(0);
      };

      const onInvert = () => {
        reset();
        setInverted((cur) => !cur);
      };

      return(
        <div>
          <div>
            <label forHtml="centimeters">centimeters</label>
            <input value={inverted ? amount*2.54 : amount} id="centimeters" placeholder="centimeters" type="number" onChange={onChange} disabled={inverted} />
          </div>
          <div>
            <label forHtml="inches">inches</label>
            <input value={inverted ? amount : amount/2.54} id="inches" placeholder="inches" type="number" onChange={onChange} disabled={!inverted} />
          </div>

          <button onClick={reset}>Reset</button>
          <button onClick={onInvert}>{inverted ? "centimeters -> inches" : "inches -> centimeters"}</button>
        </div>

       
      );
    }
 
    function KmToMiles(){
      const [amount, setAmount] = React.useState();
      const [inverted, setInverted] = React.useState(false);

      const onChange = (event) => {
        setAmount(event.target.value);
      };

      const reset = () => {
        setAmount(0);
      };

      const onInvert = () => {
        reset();
        setInverted((cur) => !cur);
      };

      return(
        <div>
          <div>
            <label htmlFor="kilometer">kilometer</label>
            <input value={inverted ? amount*1.609 : amount} id="kilometer" placeholder="kilometer" type="number" onChange={onChange} disabled={inverted}/>
          </div>
         
          <div>
            <label htmlFor="miles">miles</label>
            <input value={inverted ? amount : amount/1.609} id="miles" placeholder="miles" type="number" onChange={onChange} disabled={!inverted} />
          </div>

          <button onClick={reset}>Reset</button>
          <button onClick={onInvert}>{inverted ? "kilometer -> miles" : "miles -> kilometer"}</button>
        </div>
      );
    }

    function App(){
      const [index, setIndex] = React.useState("x");
      const onSelect = (event) => {
        setIndex(event.target.value);
      }
      return (
        <div>
          <h1>Unit Converter</h1>
          <select value={index} onChange={onSelect}>
            <option value="x">Select your units</option>
            <option value="0">Minutes & Hours</option>
            <option value="1">Cm & Inches</option>
            <option value="2">Km & Miles</option>
          </select>
          <hr/>
          {index === "x" ? "Select your units" : null}
          {index === "0" ? <MinutesToHours /> : null}
          {index === "1" ? <CmtoInches /> : null}
          {index === "2" ? <KmToMiles /> : null}
        </div>
      );
    }
   
    const root = document.getElementById("root");
    ReactDOM.render(<App />, root);
  </script>

 

select 태그안에 각 변환기를 선택할 수 있도록 하기 위해 value를 가진 option을 넣는다.

이제 select에 onChange를 주고 value 값에 따라 option을 바꿀 수 있도록 하자.

 

그리고 해당 index가 선택되면 해당 단위변환 기능을 보여주도록 한다.

index의 초기값은 x로 하여 "Select your unit" 문구가 보이도록 하자.