whatisthis?

React) React JS - practice. 단위변환기 (Unit Conversion) 본문

PRACTICE/SELF

React) React JS - practice. 단위변환기 (Unit Conversion)

thisisyjin 2022. 2. 15. 17:43

React JS 기초 예제 실습

 

-  단위 변환기   (Unit Conversion)

 

분(M) - 시간(H)

M = H * 60
H = M / 60

 

 


 

function App() {
  return (
    <div>
      <h1 className="title">Unit Converter</h1>
      <label htmlFor="minutes">Minutes</label>
      <input id="minutes" type="number" placeholder="Minutes" />
      <label htmlFor="hours">Hours</label>
      <input id="hours" type="number" placeholder="Hours" />
    </div>
  );
}

 

 

❗❗ 주의

우리는 jsx를 사용중인 것이지 HTML을 작성하는게 아니므로 몇가지 주의할 점이 있다.


예를 들면 <label for="">의 경우에는 

자바스크립트에 for이라는 예약어가 이미 존재하므로 에러가 발생하게 된다.


BUT > 우리가 지금 import한 react파일은 production용이라 에러는 안뜸.
만약 이걸 development로 바꿔주면 에러가 바로 발생함.

class도 마찬가지.(js에 이미 class가 존재하기때문.)
>> 따라서 className=""으로 작성해주고, 

htmlFor=""로 작성해주면 된다.

 

 

 

 


function App() {
  const [minutes, setMinutes] = React.useState();
  const onChange = e => {
    console.log(e.target.value);
  };
  return (
    <div>
      <h1 className="title">Unit Converter</h1>
      <label htmlFor="minutes">Minutes</label>
      <input
        onChange={onChange}
        value={minutes}
        id="minutes"
        type="number"
        placeholder="Minutes"
      />
      <label htmlFor="hours">Hours</label>
      <input value={minutes} id="hours" type="number" placeholder="Hours" />
    </div>
  );
}

 

위와 같이 작성해준다.

 

1) useState를 사용해서 minutes(data) / setMinutes(modifier함수) 선언.

2) input이 바뀔 때 (onChange 이벤트) = onChange함수 실행되도록

3) input의 value가 minutes가 되도록. (연결?)

4) input태그의 value를 받아오기 위해서 e.target.value를 사용한다. (일반 JS문법대로)

 

 

 

값이 바뀔때마다 계속해서 e.target.value를 로그함

참고 ) SyntheticBaseEvent
- react는 가짜 이벤트를 발생시킴.
console.log(e); 해보면 SyntheticBaseEvent라고 뜸!

 

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

이제 value값이 잘 나오는 것을 확인했으니, setMinutes함수에 argument로 넣어준다.

추가로, 정상적으로 작동하는지 테스트하기 위해서

<h4>You want to convert {minutes}</h4>

위와 같이 {minutes}값이 바뀐 것을 확인할  수 있는 h4태그를 만들었다.

 

잘 동작한다! : )

 

 

우리가 input의 value를 바꿀때마다 (입력할때마다)

-> 컴포넌트는 새로운 값으로 재실행되고 -> 바뀐 부분만 업데이트해줌

 


 

Recap + Revise

왜 value에 {minutes}, 즉 현재 state 데이터를 저장했는지?

 

const onClick = () => {
  // setCounter(counter + 1);
  setCounter(current => current + 1);
};

지난 포스팅에서 데이터를 직접 사용하지 않고

current값을 사용했던 것과 같은 맥락임.

(함수 외에>> 해당 값이 변경될 경우를 대비한 것.)

 

 

 

<div>
  <label htmlFor="hours">Hours</label>
  <input
    value={minutes / 60}
    id="hours"
    type="number"
    placeholder="Hours"
  />
</div>

이제 마지막으로 hours input 부분의value를 {minutes / 60}으로 해주면 끝!

 

 

 

 

 

+) 리셋 버튼 추가

<button onClick={reset}>Reset</button>
 const reset = () => {
        setMinutes(0);
};

 

>> hours부분도 연결되어있으므로 0이됨.

 

결과

 

 

단, 이 기능은 m->h변환만 가능하므로

input#hours는 입력을 못하게 막아두자.

>> disabled 속성 추가함.

 

입력 못하게 됨.

 

 

전체코드 🔻

<!DOCTYPE html>
<html>
  <body>
    <div id="root"></div>
  </body>
  <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  <script type="text/babel">
    const root = document.getElementById("root");
    function App() {
      const [minutes, setMinutes] = React.useState();
      const onChange = e => {
        setMinutes(e.target.value);
      };
      const reset = () => {
        setMinutes(0);
      };
      return (
        <div>
          <h1 className="title">Unit Converter</h1>
          <div>
            <label htmlFor="minutes">Minutes</label>
            <input
              value={minutes}
              id="minutes"
              type="number"
              placeholder="Minutes"
              onChange={onChange}
            />
          </div>

          <div>
            <label htmlFor="hours">Hours</label>
            <input
              value={minutes / 60}
              id="hours"
              type="number"
              placeholder="Hours"
              disabled
            />
          </div>
          <button onClick={reset}>Reset</button>
        </div>
      );
    }
    ReactDOM.render(<App />, root);
  </script>
</html>

 

 

 


 

 

flip 추가

 

 

flip버튼을 추가해서 h->m 변환도 가능하게 해보자.

 

 

<button onClick={onFlip}>Flip</button>

 

우선 버튼을 만들어주고,

onFlip함수를 만든다.

>> flip 여부를 알려주는 boolean데이터를 포함하는

state를 하나 더 만들어야 한다.

 

const [flipped, setFlipped] = React.useState(false);

>> flipped는 boolean값을 가지는 (기본값이 false인) 데이터이고,

setFlipped함수를 통해 flipped의 값을 바꾼다.

 

const onFlip = () => {
  setFlipped(current => !current);
  // setFlipped(!flipped);
};

flipped 변수를 그대로 사용하기보다는

current를 이용하는것이 좋다.

(current를 !current로 바꿔줌)

 

 

버튼을 클릭할 때 마다 onFlip함수가 실행되므로,처음 기본값이 false였던 flipped 값onFlip이 실행됨에 따라 setFlipped함수에 의해 !false = true가 된다.

 

 

 

<input
  value={minutes}
  id="minutes"
  type="number"
  placeholder="Minutes"
  onChange={onChange}
  disabled={flipped === true}
/>
           
/////////////////

<input
  value={minutes / 60}
  id="hours"
  type="number"
  placeholder="Hours"
  disabled={flipped === false}
/>

input#minutes와 input#hours에disabled속성을 주고, 속성값에 각각 flipped와 !flipped를 준다.

 

flipped 는 flipped===true와 같고

!flipped 는 flipped===false와 같음

 

flip 

 

 

 

이제,

onChange={onChange}를 input#hours에도 붙여넣기 해주자.

 

>> 그러면 값이 바뀔때마다 계속 그대로 출력됨.

근데? 우리가 의 value를 이미 {minutes / 60}으로 고정해놔서이상하게 바뀐다.

 

 

따라서, 이때 if-else문의 shortkey격의 식인삼항연산자를 사용한다.

조건 ? 참 : 거짓

 

 input#hours

value={flipped ? minutes : minutes / 60}

 

flipped가 참일때,

즉 input#minutes는 disabled이고  input#hours에 입력 가능할 때는

minutes를 그대로 보여주고,

 

거짓일 때는 

input#hours가 disabled이고  input#minutes에 입력하므로

minutes/60을 계산해서 결과만 보여줌.

 

input#minutes

 value={flipped ? minutes * 60 : minutes}

같은 원리로 minutes부분도 위와 같이 고쳐줌.

 

 

 

 

+) onFlip 실행될 때 마다

reset되도록 하는 기능 추가

 

 

++) 변수명 minutes를 amount로 변경

 


 

전체코드 🔻🔻🔻

 

<!DOCTYPE html>
<html>
  <body>
    <div id="root"></div>
  </body>
  <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  <script type="text/babel">
    const root = document.getElementById("root");
    function App() {
      let minToHour = true;
      const [minutes, setMinutes] = React.useState();
      const [flipped, setFlipped] = React.useState(false);
      const onChange = e => {
        setMinutes(e.target.value);
      };
      const reset = () => {
        setMinutes(0);
      };
      const onFlip = () => {
        setFlipped(current => !current);
      };

      return (
        <div>
          <h1 className="title">Unit Converter</h1>
          <div>
            <label htmlFor="minutes">Minutes</label>
            <input
              value={flipped ? minutes * 60 : minutes}
              id="minutes"
              type="number"
              placeholder="Minutes"
              onChange={onChange}
              disabled={flipped === true}
            />
          </div>

          <div>
            <label htmlFor="hours">Hours</label>
            <input
              value={flipped ? minutes : minutes / 60}
              id="hours"
              type="number"
              placeholder="Hours"
              onChange={onChange}
              disabled={flipped === false}
            />
          </div>
          <button onClick={reset}>Reset</button>
          <button onClick={onFlip}>Flip</button>
        </div>
      );
    }
    ReactDOM.render(<App />, root);
  </script>
</html>

 

 

결과

 

 

 

 

 

 

 


Ref. 

(Free Lecture)

 

 

ReactJS로 영화 웹 서비스 만들기 – 노마드 코더 Nomad Coders

React Fundamentals

nomadcoders.co

 

'PRACTICE > SELF' 카테고리의 다른 글

React JS - To Do List App(practice)  (0) 2022.02.19
React. React JS - Unit Converter (CSS추가)  (0) 2022.02.16
CSS - Position prac.03  (0) 2022.02.12
CSS - Position prac.02  (0) 2022.02.11
CSS - Position prac.01  (0) 2022.02.11