본문 바로가기

프론트엔드/ReactJS 시작하기

[React] state와 useStsate 이해하기 - 단위 변환기(1)

이번 시간에는 state에 대해 더 자세하게 배워보겠습니다. 

최종적으로 React에서 사용자들의 input을 어떻게 얻는지, form을 만들었을 때 state는 어떤식으로 작용하는지에 대해 이해해보겠니다. 우선 그 전에 먼저 앱의 state를 바꾸는 법에 대해서 배워보겠습니다. 

state를 바꾸는 2가지 방법이 있습니다.                                                                                                                                                          (useState를 통해서 얻 array 에서 데이터를 변경하는 함수를 setState라고 하겠습니다.)  

첫번째는 setState를 이용해서 state의 값을 직접 변경해주는 것입니다.  

setState(counter+1);
setState(9);
setState('lalala');

 

두번째는 현재 state를 기반으로 계산하고 싶다면 함수를 이용하는 것입니다.  setState에 함수를 넣어 이전 state를 이용해서 새로운 state를 생성합니다. 그리고 함수의 return값이 새로운 state가 됩니다.

setState((state) => state+1);

 

현재 state를 기반으로 계산하고 싶다면 리액트가 현재 state값을 보장하고 있기 때문에 이 방법이 훨씬 안전합니다.

 


 

사용자의 input을 어떻게 얻는지,  form에서 state는 어떻게 작용하는지 등 state에 대해 더 자세히 이해하기 위해서 '분 단위를 입력했을 때 시간 단위를 알려주는 단위변환기'를 만들어보는 예제를 진행하겠습니다. 

<!DOCTYPE html>
<html>
    <body>
        <div id="root"></div>
    </body>

    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

    <script type="text/babel">
         function App () {
            // minutes의 값을 input의 value로 넣어주기, input={minutes}
            // 사용자가 input에 뭔가를 입력할 때(input에 변화가 생기면), onChange라는 함수 실행
            const [minutes, setMinutes] = React.useState()
            const onChange = (event) => {
                setMinutes(event.target.value);
            };
            return (
                <div>
                    <h3>Super Converter</h3>
                    <label htmlFor="minutes">Minutes</label>
                    <input 
                        value={minutes} 
                        id="minutes"
                        placeholder="Minutes" 
                        type="number"
                        onChange={onChange}
                    />
                    <h4>You want to convert {minutes}</h4>
                    <label htmlFor="hours">Hours</label>
                    <input id="hours" placeholder="Hours" type="number"/>
                </div>
            );
        } 
        const root = document.getElementById("root");
        ReactDOM.render(<App />, root)
    </script>
</html>

결과

 1. 사용자가 입력하는 값인 input의 value를 state로 연결

2. onChange함수 ->  input에 change 이벤트가 일어났을 때  즉, 사용자가 input에 값을 입력할 때 onChange함수 실행

3. onChange 함수에서 리액트가 제공하는 event.target.value를 통해서 input value를 쉽게 가져온 후 setMinuets함수에서 minutes가 변경될 때마다 새로 update해주고 UI에 자동으로 렌더링 해줌

input의 value를 연결시켜주는 이유는 input값을 외부에서도 수정하기 위해서입니다. 따라서 연결함에 따라 input값을 통제할 수 있고  input값이 변경될때마다 event도 리스닝하고 있습니다. 

이번에는 hours도 컨트롤하여 최종적으로 단위변환기를 만들어보겠습니다.

<!DOCTYPE html>
<html>
    <body>
        <div id="root"></div>
    </body>

    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

    <script type="text/babel">
         function App () {
            // minutes의 값을 input의 value로 넣어주기, input={minutes}
            // 사용자가 input에 뭔가를 입력할 때(input에 변화가 생기면), onChange라는 함수 실행
            const [minutes, setMinutes] = React.useState()
            const onChange = (event) => {
                setMinutes(event.target.value);
            };
    
            return (
                <div>
                    <h3>Super Converter</h3>
                    <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={minutes/60}
                            id="hours"
                            placeholder="Hours" 
                            type="number"
                        />
                    </div>
                
                    
                </div>
            );
        } 
        const root = document.getElementById("root");
        ReactDOM.render(<App />, root)
    </script>
</html>

결과

분 단위를 입력하면 자동으로 시간 단위가 출력됩니다. 리액트에서는 또한 UI가 업데이트 될 때 전부 다 새로 그려지는게 아니라 오직 사용자가 입력하는 value만 리렌더링 되고 있습니다. 

Hours input은 onChange 이벤트가 없기 때문에 값을 변경할 수 없습니다. 이번에는 reset버튼을 추가하고 시간 단위도 입력가능하고 입력했을  분 단위로 출력될 수 있도록 해보겠습니다.

<!DOCTYPE html>
<html>
    <body>
        <div id="root"></div>
    </body>

    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

    <script type="text/babel">
         function App () {
            // minutes의 값을 input의 value로 넣어주기, input={minutes}
            // 사용자가 input에 뭔가를 입력할 때(input에 변화가 생기면), onChange라는 함수 실행
            const [amount, setAmount] = React.useState()
            const [flipped, setFlipped] = React.useState(false)
            const onChange = (event) => {
                setAmount(event.target.value);
            };
            // state를 리스닝하거나 연결된 모든 것들은 0으로 됨
            const reset = () => setAmount(0);
            //버튼을 눌렀을 때 flip됨, flipped이 false(기본값)라면 분->시간(disabled==true), true면 시간->분(disabled==false)
            const onFlip = () => {
                reset();
                setFlipped(flipped => !flipped );
            }   
            return (
                <div>
                    <h3>Super Converter</h3>
                    <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 : amount/60}
                            id="hours"
                            placeholder="Hours" 
                            type="number"
                            onChange={onChange}
                            disabled={!flipped}
                        />
                    </div>
                    <button onClick={reset}>Reset</button>
                    <button onClick={onFlip}>Flip</button>
                    
                </div>
            );
        } 
        const root = document.getElementById("root");
        ReactDOM.render(<App />, root)
    </script>
</html>

 

결과

따라서 분 -> 시간 변환시켜주고 flip 버튼을 누르면 시간 -> 분으로 변환시켜주는 단위변환기를 만들었습니다.

다음 시간에는 km -> mile로, mile->km로 변환시켜주는 기능까지 추가해보겠습니다.