newChobo

#4 PROPS

4.0 PROPS

저번 시간에 배운것

const [amount, setAmount] = React.useState(0);
const onChange = (event) => {
                setAmount(event.target.value);                
            }
{index === "xx" ? "Please select your units": null}
 

 

오늘

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

우리가 만드는 컴포넌트들은 괄호로 인자를 받아온다. 인자를 props, properties라고 부름

ex) 같은 스타일의 버튼 여러개를 만들때 버튼 하나하나에 스타일을 복붙하는것은 낭비. 그것을 해결해보려 함

 

리엑트가 프롭들을 자동으로 넣어주어, 내가 사전자료형처럼 넣는 효과라고 보면 됨

Btn({banana:"save changes"}) <!-- 이론상 아래와 동일함  -->
                    <Btn banana="Save Changes" />

여러개의 인자를 보낼 수도 있음.

<!DOCTYPE html>
<html>
    <body>
        <div id="root"></div>
    </body>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> <!-- JSX 를 컴퓨터가 이해하게 하기 위해 필요, type="text/babel" 로 해줘야 동작함-->

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

       
        /*function Btn(props){      //사전자료형으로 보내는 것이기 때문에, 바나나든 text든 상관 없음
            console.log(props);
            return (
                <button style={{
                    backgroundColor: "tomato",
                    color:"white",
                    padding:"10px 20px",
                    border: 0,
                    borderRadius: 10,
                }}>
                    {props.banana}
                </button>
            );
        }*/

        function Btn({text, big}){
            console.log({text, big});      // 그냥 지름길일 뿐이라 함. property를 오브젝트로부터 미리 꺼낸다
            return (
                <button style={{
                    backgroundColor: "tomato",
                    color:"white",
                    padding:"10px 20px",
                    border: 0,
                    borderRadius: 10,
                    fontSize: big ? 18 : 16,       // 삼항연산자
                }}>
                    {text}
                </button>
            );
        }

        function App(){            
            return (
                <div>
                    <Btn text="Save Changes" x={false} big={true} />
                    <Btn text="Continue" y={7} />
                </div>
            );
        }

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

=====================================================================

4.1 Memo

html태그에 쓰는 onClick과 JSX

html소스가 들어가는 부분에 쓴 것은 이벤트리스너를 등록하는 것이 맞으나, 

커스텀 컴포넌트에 onClick을 넣는것은 이벤트리스너를 등록하는것이 아님. 완전히 다르다고 볼 수 있음

                <div>
                    <Btn text="Save Changes" onClick={changeValue} />
                    <Btn text="Continue" />
                </div>

onClick리스너로 쓰일꺼라고 이름을 onClick으로 둘 필요는 없음

        function Btn({text, changeValue}){
            return (
                <button
                    onClick={changeValue}
 
 
            return (
                <div>
                    <Btn text={value} changeValue={changeValue} />    
                    <Btn text="Continue" />
                </div>
            );
prop으로 넣는다고 자동으로 들어가지 않음. 직접 넣어줘야함
 
<!DOCTYPE html>
<html>
    <body>
        <div id="root"></div>
    </body>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> <!-- JSX 를 컴퓨터가 이해하게 하기 위해 필요, type="text/babel" 로 해줘야 동작함-->

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

        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>
            );
        }

        function App(){            
            const [value, setValue] = React.useState("Save Changes");
            const changeValue = () => setValue("Revert Changes");

            return (
                <div>
                    <Btn text={value} changeValue={changeValue} />    
                    <Btn text="Continue" />
                </div>
            );
        }

        ReactDOM.render(<App />, root);        
    </script>  
</html>
//버튼을 여러번 눌러도 state는 한번만 바뀌어서 여러번 동작하지는 않는군.
내부 value값이 그대로라 변할 필요가 없는 Continue도 render되는것을 알 수 있다.
이는 낭비로 보임.
 
그래서 React Memo가 필요함
<!DOCTYPE html>
<html>
    <body>
        <div id="root"></div>
    </body>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> <!-- JSX 를 컴퓨터가 이해하게 하기 위해 필요, type="text/babel" 로 해줘야 동작함-->

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

        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>
            );
        }

        // 본래는 부모의 State가 변경되면 모든 자식이 리렌더 된다. 이게 느려지는 원인이 될 수도
        // 리엑트에게 프롭이 변하지 않는다면 바꾸지 말아주세요~ 하는 느낌이라고 함
        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>
            );
        }

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

======================

4.2 Prop Types : 리액트가 우리에게 틀렸다고 말해준다

리엑트에게 우리 prop들의 type이 뭔지 알려준다

 

<!DOCTYPE html>
<html>
    <body>
        <div id="root"></div>
    </body>
   
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> <!-- JSX 를 컴퓨터가 이해하게 하기 위해 필요, type="text/babel" 로 해줘야 동작함-->

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

        function Btn({text, fontSize = 12}){        // 기본값
            return (
                <button                
                    style={{
                    backgroundColor: "tomato",
                    color:"white",
                    padding:"10px 20px",
                    border: 0,
                    borderRadius: 10,
                    // fontSize: fontSize       // 둘이 똑같으면 자동으로 맵핑되나봄... 이건 첨보네
                    fontSize,
                }}>
                    {text}
                </button>
            );
        }

        // 대소문자 주의
        Btn.propTypes = {               //Btn.propTypes
            text: PropTypes.string.isRequired,     //PropTypes.string
            fontSize: PropTypes.number,      //isRequired가 걸린 애들은 반드시 필요함
        };

        function App(){
            return(
                <div>
                    <Btn text="Save Changes" fontSize={18} />
                    <Btn text="Continue" />                    
                </div>
            );
        }

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

==================================

4.3 Recap(요약)

1. type script는 해당하지 않지만, 인자(prop)으로 받아올 데이터형을 지정하여 오류에 대한 경고를 띄워줄 수 있음.

2. react memo를 활용해, 이미 랜더링된것과 차이가 없는 자식 컴포넌트는 다시 랜더하지 않도록 할 수 있음.

profile

newChobo

@새로운뉴비

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!