티스토리 뷰

▶JSX에 대해서 더 알아보기

-알다시피 JSX는 HTML과 매우 유사하다. 그렇기 때문에 JSX로 만들어진 것들을 HTML로 써도 문제가 없다.

그렇지만 주의할 점이 있다. label태그를 예시로 들어보자.

*label: input옆에 써주는 글씨, label을 누르면 옆에 input이 선택된다. input과 label을 연결하기 위해서는 input에 id가 필요하다. input의 아이디명과 label의 for 속성명이 같으면 된다. ->in HTML의 경우

<div>
          <h1>Supur Converter</h1>
          <label for="minutes">Minutes</label>
          <input id="minutes" placeholder="Minutes" type="number" />
          <label for="hours">Hours</label>
          <input id="hours" placeholder="Hours" type="number" />
        </div>

-> 해당 코드가 브라우저에서 정상적으로 돌아가는 이유는 우리가 react.production.min.js를 사용하기 때문이다. productiondevelopment로 바꾼다면 에러 메세지(Warning: Invalid DOM property `for`. Did you mean `htmlFor`?)가 뜬다.

결론적으로 우리가 사용하는 것은 JSX라는 것을 기억하자(HTML과 비슷하단 것이지 완전 동일하게 작동하는 것은 아니다).

  • HTML과 비슷하지만 다른 점 몇가지 기억할 것이 있다. 예를들어, JSX에서는 class를 쓸 수 없고 className 이라고 써줘야 한다는 점 또한 label의 속성으로 for 이 아니라htmlFor을 써야한다는 점 등이 있다. 우리가 class나 for을 쓸 수 없는 이유는 일단 for과 class는 JavaScript용어이기 때문이다. 즉, 이미 선점된 단어(예약어)라는 것이다. 
  • This is because JSX gets translated into JavaScript, and class is a reserved word in JavaScript. When JSX is rendered, JSX className attributes are automatically rendered as class attributes.
  • 아래는 React 공홈에 설명된 JSX관련 주의사항이다. 참고자료로 읽어보면 좋다. React DOM이 HTML 속성명을 쓸 때 카멜케이스를 사용하고 있다는 말을 하고 있다. 

Warning:

Since JSX is closer to JavaScript than to HTML, React DOM uses camelCase property naming convention instead of HTML attribute names.

For example, class becomes className in JSX, and tabindex becomes tabIndex.

 

우리는 JSX를 사용하고 있기 때문에 위의 코드에서 속성명을 수정(for -> htmlFor)해주는 작업이 필요하다.  

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

우리가 만들어 볼 것은 min 단위를 hour 단위로 변환시켜주는 unit convertor이다. 

 

아래의 코드는 input 태그의 입력값이 업데이트되는 것을 감지해서 업데이트된 값을 UI에 표시해주는 단계이다. 

  1. state를 만들기 
  2. input의 value를 state로 연결하기  e.g.)<input value={minutes}> //어디서든 input의 value를 수정가능 -> 연결한 이유는 input값을 외부에서도 수정하기 위해서임 예를들어, reset버튼을 누르면 input의 내용이 다 삭제되는 것
  3. onChange함수 만들기 - 데이터(input에서 리스닝하는 데이터)를 업데이트하는 역할을 함, 만약에 onChange함수를 삭제하게되면 입력값을 입력할 수 없게된다. Input의 value가 state고 state의 기본값이 0으로 설정되어 있기 때문이다. input이 키보드 이벤트를 감지한다해도 업데이트가 이뤄지지 않는다.
<script type="text/babel">
    //unit converter(단위 변환기)를 만들어보자
    //1. min to seconds
    const root = document.getElementById("root");

    function App() {
      const [minutes, setMinutes] = React.useState(0);
      const onChange = (event) => {
        setMinutes(event.target.value);
      };
      return (
        <div>
          <h1>Supur Converter</h1>
          <h4>you need to convert {minutes}</h4>
          <label htmlFor="minutes">Minutes</label>
          <input
            id="minutes"
            value={minutes}
            placeholder="Minutes"
            type="number"
            onChange={onChange}
          />
          <label htmlFor="hours">Hours</label>
          <input id="hours" placeholder="Hours" type="number" />
        </div>
      );
    }

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

JSX를 이용하고 있기 때문에 javascript의 event 객체를 똑같이 이용할 수 있는데 입력받은 값을 알아내기 위해 modifier 함수에 event 를 전달하고 event.target.value를 통해 입력된 값에 접근이 가능하다. ->이 말은 즉 document.getElementby 어쩌구 하는 이전에 JS작업을 할 필요가 없다는 소리다. 

  • *target이 정확히 무엇을 가리키는 지 모르겠다면 console.log(event.target)을 해서 확인해보면 된다. 위의 코드의 경우엔 input태그를 가리킨다. 결국 event.target.value가 우리가 찾던 값이 맞다.
  • console.log(event)를 해보면 SyntheticBaseEvent(*synthetic 합성의)가 뜬다. 이유는 바로 React JS가 가짜 event를 발생시키기 때문이다. native JavaScript event 객체(원래 event객체)를 보고 싶다면 리액트 이벤트 내부에 "nativeEvent"를 확인해보면 된다. 요지는 우리가 JS의 event객체를 리액트에서도 사용할 수 있다는 점이니 더 자세한 내용은 아래의 링크를 통해서 확인하면 된다. 

https://reactjs.org/docs/events.html

 

SyntheticEvent – React

A JavaScript library for building user interfaces

reactjs.org


 

▶완성된 코드

1. reset 버튼 - mins와 hours의 입력값 초기화하는 기능 

2. flip 버튼 - 기본값 mins 활성화 hours 입력 비활성화/ flip버튼 누를시 반대로

  • onFlip 함수 내부에 reset 함수 호출을 통해 기존 값 초기화 필요

3. 3항 연산자를 통해 mins와 hours 값 flip시에도 제대로된 값을 UI에 표시

<script type="text/babel">
    //unit converter(단위 변환기)를 만들어보자
    //1. min to second, second to min
    const root = document.getElementById("root");

    function App() {
      const [amount, setAmount] = React.useState(0);
      const [flipped, setFlipped] = React.useState(false);
      const onChange = (event) => {
        setAmount(event.target.value);
      };
      const reset = () => setAmount(0);
      const onFlip = () => {
        reset();
        setFlipped((current) => !flipped);
      };
      return (
        <div>
          <h1>Supur Converter</h1>
          <div>
            <label htmlFor="amount">Minutes</label>
            <input
              id="amount"
              value={flipped ? amount * 60 : amount}
              placeholder="Minutes"
              type="number"
              onChange={onChange}
              disabled={flipped}
            />
          </div>
          <div>
            <label htmlFor="hours">Hours</label>
            <input
              value={(flipped ? amount : Math.round(amount / 60)}
              id="hours"
              placeholder="Hours"
              type="number"
              onChange={onChange}
              disabled={!flipped}
            />
          </div>
          <button onClick={reset}>Reset</button>
          <button onClick={onFlip}>{flipped ? "Turn back" : "Flip"}</button>
        </div>
      );
    }

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

-input 태그의 disabled 속성은 인풋을 비활성화 시킨다. 

-flipped 의 초기값은 false이다. 이 속성을 이용해서 input 태그의 disabled속성 값이 !flipped(true)이면 비활성화 상태, 반대면 활성화 상태임을 설정할 수 있음

-JSX 내에서 JS의 연산식을 사용할 수 있으므로 활용해서 쓰기, 3항 연산자의 경우 flipped 됐을 때의 상황을 판단해서 true일때 false일 때 각각에 맞는 값을 화면에 출력하기 위함 

  • Minutes input에서 우리가 flipped인 상황이라면 시에서 분 단위로 변환중이니까 그 값은 amount*60이됨 not flipped인 상황이면 그냥 우리가 입력한 값을 보여주면 된다. 
  • Hours input에서 우리가 flipped인 상황이라면 현재 시에서 분단위로 변환하고 있는 상태라는 얘기고 그냥 우리가 쓴 숫자를 input창에 보여주면 된다. not flipped인 상황이면 amount/60 값을 보여준다. 
  • 여기서 명심해야할 점은 flipped인 상황이라는 것은 hours에 입력한다는 것

-기존에 minutes 가 hours와 같은 기능(onChange)을 구현하고 있으므로 minutes -> amount로 명을 바꿔 혼선방지

-{flipped ? "Turn back" : "Flip"} 코드는 유저가 flip상태인지 아닌지에 대해서 확실하게 알려주기 위해 버튼명을 변경해주기위해 삼항연산자를 활용한 것

댓글