본문 바로가기
Web Service/React

[영화 웹 서비스 만들기] #5. State

by junnykim 2022. 3. 21.

~3.9까지의 강의

역대급으로 긴 호흡이라 집중이 잘 안되는 것 같기도하고

길어서 전체 코드 대신에 부분 적으로 코드를 보도록 하도록 하자.

 

 

setCounter을 설정해서 원하는 값으로 변경해주자.

이때 setCounter는 이전 값을 이용해서 현재 값을 계산해 내는 것 이기 때문에, setCounter를 다르게 설정해 줄 수 있다.

 

1. 직접 값 설정

 setCounter(counter+1);

정해진 값으로 나옴.

 

2. 함수 전달

setCounter((current) => current+1);

현재 값을 가지고 계산을 해야 한다면, setCounter 안에 함수를 넣자. 이렇게 한다면 다음 state 값이 현재 값을 바탕으로 나온다. 즉, 함수가 언제나 현재 state를 얻을 수 있도록 해줄 것이다.

 

<!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">
        function App(){
            const [counter,setCounter] = React.useState(0);
            const onClick = () => {
               setCounter((current) => current+1);
            };
            return (
                <div>
                    <h3>Total clicks: {counter}</h3>
                    <button onClick={onClick}>Click me</button>
                </div>
            );
        }
        ReactDOM.render(<App/ >, root);
    </script>
</html>

결국 클릭할 때마다 current가 늘어나고, 이게 data(=counter)로 보여지는 것!

 

 


onChange

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

input의 value로 data(=minutes)를 넣어주면, state의 value(minutes)와 같아 진다. input에 변화가 생길 때마다, onChange가 발생한다. 타겟은 방금 바뀐 input이다. value를 minutes에 넣어주기는 하지만, 데이터를 업데이트 하는 방법는 setState 함수를 사용하는 것이다. 

input 값을 value로 연결해주면 어디서든 input의 value를 수정할 수 있다.

onChage는 데이터를 업데이트 하는 역할을 하는데, 이것은 우리가 onChange를 삭제한다고 해도 state에 연결된 input값은 연결되어 value로 보여준다. input은 스스로 업데이트를 하고, input 값을 외부와도 연결시킨다. 

 

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

onChange에서 값이 의미하는 것은 setMinutes의 이벤트의 target의 value이다. 콘솔로 찍어보면 알 수 있음.

 

<!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">
        function App(){
        const [minutes,setMinutes]=React.useState();
           const onChange=(event)=>{
                // console.log(event.target.value);
                setMinutes(event.target.value);
           } 
            return (
                <div>
                    <h1 className="hi">Super Converter</h1>
                    <label htmlFor="minutes">Minutes</label>
                    <input
                        value={minutes} 
                        id="minutes" 
                        placeholder="Minutes" 
                        type="number"
                        onChange={onChange}
                    />
                    <h4>You want to convert {minutes}</h4>
                    <label for="hours">Hours</label>
                    <input id="hours" placeholder="Hours" type="number"/>
                </div>
            );
        }
        ReactDOM.render(<App/ >, root);
    </script>
</html>

 

 


 

onReset을 만들어 보자. onReset은 말그대로 리셋해주는 버튼이다. 이때 setstate 값을 디폴트로 0으로 하자.

 

<!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">
        function App(){
            const onReset=(event)=>{
                setMinutes(0);
            }
           const [minutes,setMinutes]=React.useState(0);
           const onChange=(event)=>{
                setMinutes(event.target.value);
           } 
            return (
                <div>
                    <h1>super converter</h1>
                    <div>
                        <label htmlFor="minute">Minutes</label>
                        <input
                            value={minutes} 
                            id="minute" 
                            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"
                        />
                    </div>
                    <button onClick={onReset}>Reset</button>
                </div>
            );
        }

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

또, 위와는 달리 minutes의 값에 따라 hours의 값도 변화한다. 값에 수식을 넣어주면 간단하게 해결이 가능하다. 

 

 

분에 따라 시간이 달라지는 것과, Reset 버튼을 눌렀을 때


 

flip이라는 버튼이 생겼다. 

disabled={flipped}

이것의 의미는, flip되었을 때 disabled 되게(input 전체가) 한다는 의미이다.

 

const isFlipped=(event)=>{
  reset();
  setFlipped((current)=> !current);
}

inFlipped함수는 event가 실행 되었을 때, 먼저 reset하고, 현재의 상태를 바꾼다. 그래서 버튼 누르면 상태가 바뀌는 것.

 

<!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">
        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 isFlipped=(event)=>{
                reset();
                setFlipped((current)=> !current);
            }
            return (
                <div>
                    <h1>Super Converter</h1>
                    <div>
                        <label htmlFor="minute">Minutes</label>
                        <input
                            value={flipped?amount*60:amount} 
                            id="minute" 
                            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={isFlipped}>Flip</button>
                    <button onClick={reset}>Reset</button>
                </div>
            );
        }
        const root = document.getElementById("root");
        ReactDOM.render(<App/ >, root);
    </script>
</html>

막혀 있고, 플립 누른 후 reset 후에 상태를 바뀐다. 처음에는 minutes가 막히고, 그 후는 바껴서 hours가 막힘

 


 

이제 자주 쓰이는(정확히는 Nwitter하면서 많이 사용하는) 문법에 대해서 배운다.

{inverted ? "Turn back":"Invert"}

flip을 invert로 변경하고,  위의 문법과 같은 것으로 변경했다. 뭐 이건 너무 기본이지만, 값이 true면 Turn back이, false면 invert로 바뀌는 것이다. 그래서 위는 계속 버튼이 Flip이지만, 얘는 내가 지금 무슨 상태인가!를 확인할 수 있다.

 

<!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">
        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=(event)=>{
                reset();
                setInverted((current)=> !current);
            }
            return (
                <div>
                    <h1>Super Converter</h1>
                    <div>
                        <label htmlFor="minute">Minutes</label>
                        <input
                            value={inverted?amount*60:amount} 
                            id="minute" 
                            placeholder="Minutes" 
                            type="number"
                            onChange={onChange}
                            disabled={inverted}
                        />
                    </div>
                    <div>
                        <label htmlFor="hours">Hours</label>
                        <input 
                            value={inverted?amount:Math.round(amount / 60)}  
                            id="hours" 
                            placeholder="Hours" 
                            type="number"
                            onChange={onChange}
                            disabled={!inverted}
                        />
                    </div>
                    <button onClick={reset}>Reset</button>
                    <button onClick={onInvert}>{inverted ? "Turn back":"Invert"}</button>
                </div>
            );
        }
        const root = document.getElementById("root");
        ReactDOM.render(<App/ >, root);
    </script>
</html>

 

 

첫 번째는 동일하고, Invert 눌렀을 때 Turn back으로 바뀜

 


 

이제 Select 함수에서의 JSX를 배우는데, 이건 다 배운 것들이다.

그냥 if-else문을 쓰면 글자로 인식하지만, {}안에 쓰면 JS를 사용할 수 있다.

 

나머지는 다 비슷하고, select만 조금 확인해보자. 

 function App(){
            const [index,setIndex] = React.useState("xx");
            const onSelect = (event) => {
                setIndex(event.target.value);
            };
            console.log("render w/", index);
            return(
                <div>
                    <h1 className="title">Unit 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>
                    <hr/>
                    {index === "xx" ? "Please select your units" : null}
                    {index === "0" ? <MinutesToHours /> : null}
                    {index === "1" ? <KmToMiles /> : null}
                </div>
            );
        }

먼저 index를 사용해 값을 선택할 수 있도록 한다. index는 0,1로 되어 있으므로 초기값은 xx로 설정한다. onSelect의 값은 위와 마찬가지로 event의 target의 value이다.

 

더보기
더보기
<!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">

        function MinutesToHours(){
            const [time, setTime] =React.useState(0);
            const [inverted, setInverted] = React.useState(false);
            const onChange =(event)=>{
                setTime(event.target.value);
            };
            const Reset = () => setTime(0);
            const onInvert = (event) => {
                Reset();
                setInverted((current) => !current);
            };
            return(
                <div>
                    <div>
                        <label htmlFor="minutes">Minutes</label>
                        <input 
                            id="minutes" 
                            placeholder="Minutes" 
                            type="number"
                            value={inverted ? time*60 : time}
                            onChange={onChange} 
                            disabled={inverted}
                        />
                    </div>
                    <div>
                        <label htmlFor="hours">Hours</label>
                        <input 
                            id="hours" 
                            placeholder="Hours" 
                            type="number"
                            value={inverted ? time : Math.round(time/60)}
                            onChange={onChange} 
                            disabled={!inverted}
                        />
                    </div>
                    <button onClick={Reset}>Reset</button>
                    <button onClick={onInvert}>{inverted? "Turn back" : "Invert"}</button>
                </div>
            )
        }

        function KmToMiles(){
            const [length, setLength] =React.useState(0);
            const [inverted, setInverted] = React.useState(false);
            const onChange =(event)=>{
                setLength(event.target.value);
            };
            const Reset = () => setLength(0);
            const onInvert = (event) => {
                Reset();
                setInverted((current) => !current);
            };
            return(
                <div>
                    <div>
                        <label htmlFor="kilometer">Kilometer</label>
                        <input 
                            id="kilometers" 
                            placeholder="Kilometers" 
                            type="number"
                            value={inverted ? (length*1.609) : length}
                            onChange={onChange} 
                            disabled={inverted}
                        />
                    </div>
                    <div>
                        <label htmlFor="mile">Mile</label>
                        <input 
                            id="miles" 
                            placeholder="Mile" 
                            type="number"
                            value={inverted ? length : (length/1.609)}
                            onChange={onChange} 
                            disabled={!inverted}
                        />
                    </div>
                    <button onClick={Reset}>Reset</button>
                    <button onClick={onInvert}>{inverted? "Turn back" : "Invert"}</button>
                </div>
            )
        }

        function App(){
            const [index,setIndex] = React.useState("xx");
            const onSelect = (event) => {
                setIndex(event.target.value);
            };
            console.log("render w/", index);
            return(
                <div>
                    <h1 className="title">Unit 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>
                    <hr/>
                    {index === "xx" ? "Please select your units" : null}
                    {index === "0" ? <MinutesToHours /> : null}
                    {index === "1" ? <KmToMiles /> : null}
                </div>
            );
        }
        const root = document.getElementById("root");
        ReactDOM.render(<App/ >, root);
    </script>
</html>

처음에 xx일 때와, select!

 

~와 드디어 3강 끝~

댓글