노마드코더 ReactJS로 영화 웹 서비스 만들기 3 (state)

딩쓰·2022년 12월 13일
0
post-thumbnail

3. [2021 UPDATE] STATE

#3.5 ~ # 3.9

Inputs and State (단위 변환기)

  • 이제 input 태그로 unit conversion(단위 변환기)를 만들기 위해 페이지를 초기화 했음.
    • 단위 변환기: 분을 입력하면 시간으로 변환하고, 시간을 입력하면 분으로 변환하는것.
<script type="text/babel">
  const root = document.getElementById('root');
  
  function App() {
    return (
      <div>
        <h1>Super Converter</h1>
      </div>
    );
  }

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

JSX에서는 JS의 키워드를 쓰면 안됨!

  • JSX가 html과 쓰는 방식이 비슷해도 html 쓰듯이 코드를 작성하면 안됨
  • 밑의 코드처럼 class , for은 JS에 이미 있는 예약어라서 쓰면 오류가 나게 됨.
<script type="text/babel">
  const root = document.getElementById('root');
  
  function App() {
    return (
      // js가 선점한 키워드는 사용하면 안됨. for, class 같은 것들은 JS용어라서 나중에 오류생김
      <div>
        <h1 class="hi">Super 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>
    );
  }

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

그럼 JSX용어를 써서 바꿔주자!

  • class => className , For => htmlFor 로 바꿈.
  • <label>은 input옆에 써주는 글. <label>에 있는 글씨를 누르면 그 옆 input이 선택됨
    • <label>을 input에 연결시키기 위해선 for(JSX에선htmlFor)로 연결해야함.
<script type="text/babel">
  const root = document.getElementById('root');
  
  function App() {
    return (
      // js가 선점한 키워드는 사용하면 안됨. for, class 같은 것들은 JS용어라서 나중에 오류생김
      <div>
        <h1 className="hi">Super Converter</h1>
        <label For="minutes">Minutes</label>
        <input id="minutes" placeholder="Minutes" type="number" />
        <label htmlFor="hours">Hours</label>
        <input id="hours" placeholder="Hours" type="number" />
      </div>
    );
  }

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

이제 value값이 바뀌면 onChange함수를 이용해서 input값을 새로고침 해줄 것임.
이때, onChange함수에 event를 받아오면 콘솔창에서 event객체를 확인할 수 있음.

    function App() {
      const [minutes, setMinutes] = React.useState();
      const onChange = (event) => {
        console.log(event);
      };
      
      return (
        <div>
            <h1 className="hi">Super Converter</h1>
            <label htmlFor="minutes">Minutes</label>
            <input
              value={minutes}
              id="minutes"
              placeholder="Minutes"
              type="number"
              onChange={onChange}
            />
        </div>
      );
    }
  • nativeEvent 이벤트 객체를 확인하면 event.target.value로 input값을 받을 수 있는걸 볼 수 있음.
    => JS이벤트 사용 가능.

분 -> 시

  • 이제 setState함수에 event.target.value을 넣어주고, 분 -> 시를 만들 input창도 하나 더 만들어줘서 onChange()함수에 연결하자.
  • Math.round()를 써서 120분 -> 2시간 이런식으로 소수점을 없앰.

function App() {
      const [minutes, setMinutes] = React.useState();
      const onChange = (event) => {
        setMinutes(event.target.value);
      };

      return (
        <div>
          <div>
            <h1 className="hi">Super Converter</h1>
            <label htmlFor="minutes">Minutes</label>
            <input
              value={minutes}
              id="minutes"
              placeholder="Minutes"
              type="number"
              onChange={onChange}
            />
          </div>
          <div>
            <label htmlFor="hours">Hours</label>
            <input
              value={Math.round(minutes / 60)} 
              id="hours"
              placeholder="Hours"
              type="number"
              onChange={onChange}
            />
          </div>
        </div>
      );
    }

✅ 분 -> 시간 변환되는 모습

reset 버튼 생성

function App() {
    // const [data, data를 수정하기 위한 함수]=useState(default data)
    const [minutes, setMinutes] = React.useState(0);

    // onChange함수가 없고 default data값이 0이면 값은 절대 수정이 안됨
    const onChange = (event) => {
      setMinutes(event.target.value);
    }
    const reset = () => setMinutes(0);
    return (
      //  for, class 같은 것들은 js가 선점한 키워드라서 사용하면 안됨. 나중에 오류생김.
      <div>
        <h1 className="hi">Super Converter</h1>
        <div>
          <label htmlFor="minutes">Minutes</label>
          <input value={minutes} id="minutes" placeholder="Minutes" type="number" onChange={onChange} />
        </div>

        <div>
          <label htmlFor="hours">Hours</label>
          <input value={Math.floor(minutes/60)} id="hours" placeholder="Hours" type="number" />
        </div>
        <button onClick={reset}>Reset</button>
      </div>
    );
  }
  • reset()함수를 생성해주고, reset 버튼도 만들어줌.
  • reset버튼을 누르면 0으로 리셋됨.

분->시, 시->분 만들기

Flip 버튼 만들기

const onFlip = () => setFlipped((current) => !current);

<button onClick={onFlip}>Flip</button>
  • onFlip함수를 만들고, Flip버튼에 onClick 이벤트를 생성해줌.

disabled을 이용해서 flip기능 활용하기

function App() {
    const [minutes, setMinutes] = React.useState(0);
    const [flipped, setFlipped] = React.useState(false);
    const onChange = (event) => {
      setMinutes(event.target.value);
    }
    const reset = () => setMinutes(0);
    const onFlip = () => setFlipped((current) => !current);
    return (
      // for, class 같은 것들은 js가 선점한 키워드라서 사용하면 안됨. 나중에 오류생김.
      <div>
        <h1 className="hi">Super Converter</h1>
        <div>
          <label htmlFor="minutes">Minutes</label>
          <input 
             value={minutes}
             id="minutes" 
             placeholder="Minutes"
             type="number" 
             onChange={onChange}
             disabled={flipped === true} 
             />
        </div>

        <div>
          <label htmlFor="hours">Hours</label>
          <input 
             value={Math.floor(minutes/60)} 
             id="hours"
             placeholder="Hours"
             type="number" 
             disabled={flipped === false}
           />
        </div>
        <button onClick={reset}>Reset</button>
        <button onClick={onFlip}>Flip</button>
      </div>
    );
  }
  • disabled을 이용해서 flip(서로 바뀌는것)을 만들어 줄거임
  • disable = true : input창이 비활성화
  • disable = false : input창이 활성화
  • const [flipped, setFlipped] = React.useState(false): 초기값을 false로 설정
  • disabled={flipped === false}
    => 위의 문장의 뜻은 flipped의 값이 false면
    ( flippped === false -> true -> 창이 비활성화됨)

disable 식 축약하기

<input 
   value={minutes} 
   id="minutes"
   placeholder="Minutes" 
   type="number" 
   onChange={onChange} 
   disabled={flipped} //여기
 />
  
<input 
   value={Math.floor(minutes / 60)} 
   id="hours" 
   placeholder="Hours" 
   type="number" 
   disabled={!flipped} //여기
/> 
  • !를 사용해 축약 할 수 있음.

삼항 연산자로 flip 하기

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 = () => setFlipped((current) => !current);
    return (
    // for, class 같은 것들은 js가 선점한 키워드라서 사용하면 안됨. 나중에 오류생김.
      <div>
        <h1 className="hi">Super Converter</h1>
        <div>
          <label htmlFor="minutes">Minutes</label>
          <input   //삼항 연산자 사용
             value={flipped ? amount*60 : amount} 
             id="minutes" 
             placeholder="Minutes" 
             type="number" 
             onChange={onChange} 
             disabled={flipped} />
        </div>

        <div>
          <label htmlFor="hours">Hours</label>
          <input  //삼항 연산자 사용
             value={flipped ? amount : Math.floor(amount / 60)}            
             id="hours" 
             placeholder="Hours" 
             type="number" 
             disabled={!flipped} 
             onChange={onChange} 
           />
       </div>
        <button onClick={reset}>Reset</button>
        <button onClick={onFlip}>Flip</button>
      </div>
    );
  }
  • 삼항연산자: if문을 인라인 형태로 작성한 것.
    • { 조건값 ? 조건값이 true일때 보여줄것 : 조건값이 false일때 보여줄것}
  • {flipped ? amount*60 : amount}
    • flipped가 true일때 변환된 값(amount*60)을 보여주고 flipped가 false일때 state에 있는 값(amount)을 그대로 보여줌

최종결과

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

  function App() {
    const [amount, setAmount] = React.useState(0);
    const [inverted, setInverted] = React.useState(false);
  
    const onChange = (event) => {
      setAmount(event.target.value);
    }
  
    const reset = () => setAmount(0);
    const onInvert = () => setInverted((current) => !current);
    return (
// for, class 같은 것들은 js가 선점한 키워드라서 사용하면 안됨. 나중에 오류생김.
      <div>
        <h1 className="hi">Super 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="hours">Hours</label>
          <input
             value={inverted ? amount : Math.floor(amount / 60)} 
             id="hours" 
             placeholder="Hours" 
             type="number" 
             disabled={!inverted} 
             onChange={onChange} 
           />
        </div>
        <button onClick={reset}>Reset</button>
        <button onClick={onInvert}>{inverted ? "Turn back" : "Invert"}</button>
      </div>
    );
  }

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

✅결과 화면

킬로미터->마일 변환기

 function KmToMiles() {
      const [amount, setAmount] = React.useState(0);
      const [inverted, setInverted] = React.useState(false);
      const onChange = (event) => {
        setAmount(event.target.value);
      };
      const reset = () => setAmount(0);
      const onInvert = () => {
        reset();
        setInverted((current) => !current);
      };
      return (
        <div>
          <div>
            <label htmlFor="kilometer">Kilometer</label>
            <input
              value={inverted ? Math.round(amount / 0.62137) : amount}
              id="kilometer"
              placeholder="Kilometer"
              type="number"
              onChange={onChange}
              disabled={inverted}
            />
          </div>

          <div>
            <label htmlFor="mile">Mile</label>
            <input
              value={inverted ? amount : amount * 0.62137}
              id="mile"
              placeholder="Mile"
              type="number"
              disabled={!inverted}
              onChange={onChange}
            />
          </div>
          <button onClick={reset}>Reset</button>
          <button onClick={onInvert}>
            {inverted ? "Turn back" : "Invert"}
          </button>
        </div>
      );
    }
  • 위에서 했던 분->시 변환기 컴포넌트를 이용해서 단위만 바꿔주면 된다.
  • 1km = 0.62137마일
 function App() {
      const [index, setIndex] = React.useState("xx");

      const onSelect = (event) => {
        setIndex(event.target.value);
      };
      console.log("render w/", index);
      return (
        <div>
          <h1>Super Converter</h1>
          <select value={index} onChange={onSelect}>
            <option value="xx">select your units</option>
            <option value="0">Minutes & Hours</option>
            <option value="1">KM & Miles</option>
          </select>
          {index === "0" ? <MinutesToHours /> : null}
          {index === "1" ? <KmToMiles /> : null}
        </div>
      );
    }
    const root = document.getElementById("root");
    ReactDOM.render(<App />, root);
  • App컴포넌트 변경함
  • html <select>태그로 <option>태그를 넣어서 분->시 변환기랑 km=>mile 변환기중 선택할 수 있음
  • 삼항 연산자와 value에 숫자를 주고 인덱스처럼 활용해서 value값이 바뀔 때마다 페이지를 리렌더링 할 수 있음.

최종코드의 순서는 이렇게 됨.

✅ 결과화면

profile
Frontend Developer

0개의 댓글