본문 바로가기

웹공부/React

React 공부 2일차

*component란 어떤 JSX를 반환하는 함수라고 생각하면 된다.

 

<단위 변환기 만들기>

-km <-->miles

-minutes <-->hours

 

 

-단위 변환에 필요한 flip 버튼 생성

-옵션 변경 위한 select 생성하기

-새롭게 배운 const [A , B] = React.useState()개념 사용

     A: state값

     B: state값 재설정하는 modifier

useState에서 modifier함수를 실행하면 해당 component가 새로 rendering됨.

 

<!DOCTYPE html>
<html>
    <body>
        <div id="root"></div>
    </body>
    <script type = "text/babel">
        //flipped인 상태: hours를 입력받는 상태(!flipped = min을 입력받는 상태)
        function MinutesToHours(){
            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) => !current);
            }
            return (
                <div>
                    <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.round(amount/60)}
                        id="hours"
                        placeholder = "Hours"
                        type = "number"
                        onChange = {onChange}
                        disabled={!flipped}
                        />
                    </div>
                    <button onClick={reset}>Reset</button>
                    <button onClick={onFlip}>Flip</button>
                </div>
            );
        }
        function KmToMiles(){
            const [length, setLength] = React.useState(0);
            const [flipped, setFlipped] = React.useState(false);
            const onChange = (event) => {
                setLength(event.target.value);
            };
            const reset = () => setLength(0);
            const onFlip =() => {
                reset();
                setFlipped((current) => !current);
            }
            return (
                <div>
                    <div>
                        <label htmlFor = "Km">Km</label>
                        <input
                        value = {flipped? length / 0.621371: length}
                        id = "km"
                        placeHolder = "Km"
                        type = "number"
                        onChange = {onChange}
                        disabled = {flipped}
                        />
                    </div>
                    <div>
                        <label htmlFor = "Miles">Miles</label>
                        <input
                        value = {flipped? length : length * 0.621371}
                        id = "miles"
                        placeHolder = "miles"
                        type = "number"
                        onChange = {onChange}
                        disabled = {!flipped}
                        />
                    </div>
                    <button onClick={reset}>Reset</button>
                    <button onClick={onFlip}>Flip</button>
                </div>
            )
        }
        function App(){
            const [index, setIndex] = React.useState("xx");
            const onSelect = (event) => {
                setIndex(event.target.value);
            }
            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 == "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>

-----------------------------------------------------------------------------------------------------------------------------------------------------------------*Props: 부모 컴포넌트로부터 자식 컴포넌트에 데이터를 보낼 수 있게 해주는 방법

button 스타일 그대로 적용해서 글자만 바꿔 생성하는 코드

<!DOCTYPE html>
<html>
    <body>
        <div id="root"></div>
    </body>
    <script type = "text/babel">
        //flipped인 상태: hours를 입력받는 상태(!flipped = min을 입력받는 상태)
        function Btn({text,  big}){
            console.log(text, big);
            return <button style ={{
                backgroundColor: "tomato",
                color:"white",
                padding: "10px 20px",
                border: 0,
                borderRadius: 10,
                fontSize: big? 18 : 13
            }}>{text}</button>
        }
       
        function App(){
            return (
                <div>
                    <Btn text="Save changes"/>
                    <Btn text="Continue" big={false}/>
                </div>
            );
        }
        const root = document.getElementById("root");
        ReactDOM.render(<App />, root);
    </script>
</html>

------------------------------------------------------------------------------------------------------------------------------------------------------------

해당 Btn에 추가되는 onClick = {changeValue}은 eventListener가 아님. 단지 props이름 중 하나일 뿐.

동작하게 하려면 html 태그에 직접 추가해야 함.

function App(){
            const [value, setValue] = React.useState("Save Changes");
            const changeValue = () =>setValue("Revert Changes")
            return (
                <div>
                    <Btn text={value} onClick = {changeValue}/>
                    <Btn text="Continue" />
                </div>
            );
        }

->html 태그를 선언해놓은 Btn 함수로 가서 매개변수로 props 이름을 받은 후

function Btn({text, onClick})

->html tag <button />에 명시해줘야 동작함.

<button
                onClick={onClick}

 

***불필요한 re-render를 React.memo()로 관리하기***

원래 부모 component state에 변화가 생기면, 자식 컴포넌트 전체가 re-render가 일어남.

이 경우 state 변화가 없는 자식 component들도 함께 rerender가 일어나는데, 이 경우 React.memo()를 이용해

prop 변경이 일어난 부분만 rendering 시킬 수 있음.

* React.memo()
컴포넌트가 React.memo()로 wrapping 될 때, React는 컴포넌트를 렌더링하고 결과를 Memoizing 함. 그리고 다음 렌더링이 일어날 때 props가 같다면, React는 Memoizing된 내용을 재사용 함.

<!DOCTYPE html>
<html>
    <body>
        <div id="root"></div>
    </body>
    <script type = "text/babel">
        //flipped인 상태: hours를 입력받는 상태(!flipped = min을 입력받는 상태)
        function Btn({text, changeValue}){
            console.log(text, "was rendered.");
            return (
       
                <button
                onClick={changeValue}
                style ={{
                backgroundColor: "tomato",
                color:"white",
                padding: "10px 20px",
                border: 0,
                borderRadius: 10,
               
            }}>{text}</button>
           
            )
        }
       const MemorizedBtn = React.memo(Btn);
        function App(){
            const [value, setValue] = React.useState("Save Changes");
            const changeValue = () =>setValue("Revert Changes")
            return (
                <div>
                    <MemorizedBtn text={value} changeValue = {changeValue}/>
                    <MemorizedBtn text="Continue" />
                </div>
            );
        }
        const root = document.getElementById("root");
        ReactDOM.render(<App />, root);
    </script>
</html>

보다시피, Revert Change만 re-render가 일어나고, Continue에선 re-render가 마지막에 일어나지 않았음.

------------------------------------------------------------------------------------------------------------------------------------------    

React에서는 prop의 type이 잘못전달되었어도, 개발자가 뭘 전달하고자 하는지 파악하지 못하므로, 오류메시지가 뜨지 않음. 아래와 같이 propTypes를 사용자가 직접 지정해 다른 타입이 입력되면, 에러창을 띄워줄 수 있음.

이는 오류감지와 의도치않은 실수를 미연에 방지해줌.

 
    const MemorizedBtn = React.memo(Btn);


        MemorizedBtn.propTypes = {
            //props의 type이 무엇이고 어떤 형태여야하는지 정의
            text: PropTypes.string,
            fontSize: PropTypes.number.isRequired,
        }

'웹공부 > React' 카테고리의 다른 글

React 공부 6일차  (0) 2023.08.17
React 공부 5일차  (0) 2023.08.15
React 공부 4일차  (0) 2023.08.13
React 공부 3일차  (0) 2023.08.11
React 공부 1일차  (0) 2023.08.04