WEB/React

[영화 웹] #4. PROPS

Harimad 2022. 1. 28. 00:03

 

노마더코드 깃 히스토리: https://github.com/nomadcoders/react-for-beginners/commits/master

#4.0 Props

props는 부모 컴포넌트로부터 자식 컴포넌트에게 데이터를 전송하는 방식이다.


부모에 props를 사용하면 자식 컴포넌트(함수)의 인자로 객체가 들어가게 된다.


하나의 버튼을 만들어서 props를 이용해서 버튼의 스타일을 관리함으로써 재사용성이 높아진다.

https://devdocs.io/react/components-and-props

 

DevDocs

 

devdocs.io

 

App 컴포넌트에서 Btn 컴포넌트를 사용할때, <Btn text="hello" big={true} />처럼

사용자가 원하는 인자값을 Btn 컴포넌트에 넣어줄 수 있다.

인자값을 받을떄는 function Btn( { text, big }) {~~~} 처럼 파라미터를 객체로 기입해야 한다.

그러면 객체안의 변수들을 Btn 컴포넌트 안에서 그대로 사용할 수 있다.

 

이것보다 더 편한 방식이 function Btn (props) {~~~} 처럼 props를 이용하는 것이다.

props는 object type이므로 Btn컴포넌트 안에서 사용할때는 props.name 처럼 하면 된다.

장점 : 객체를 구조분해 할당 사용하면 매우 유용하다

<!DOCTYPE html>
<html>

<body>
<div id="root"></div>
<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 Btn({ text, big }) {
    console.log(text, big);
    return (
        <button
            style={
                {
                    background: 'tomato',
                    color: 'white',
                    padding: '10px 20px',
                    border: 9,
                    borderRadius: 10,
                    fontSize: big ? 18 : 8,
                }
            }
        >
            {text}
        </button>
    );
}

function App() {
    return (
        <div>
            <Btn text="First btn props" big={true} />
            <Btn text="Second btn props" big={false} />
        </div>
    ); //<Btn text="~~"/> 는 실제로 Btn({text: "Save Changes"}) 와 같다
}
const root = document.querySelector('#root');
ReactDOM.render(<App />, root);
</script>
</body>

</html>

 

#4.1 Memo

일반적으로 컴포넌트 쓸 때 주의점 :

 

App 컴포넌트에서 Btn컴포넌트를 다음과 인자를 넣어주고 이와같이 썼다

<Btn text={value} onChangeValue={changeValue} />
<Btn text="Continue" />
 
그러면 Btn Tag가 클릭이 되면 App 컴포넌트 안에 있는 changeValue함수가
setValue함수를 호출하면서 useState 함수를 쓰게된다.
그러면 App컴포넌트의 return 부분이 전체적으로 Rerendering 된다.
만약에 App컴포넌트가 Rerendering 해야될 컴포넌트가 많다면, 성능저하의 원인이 될 수 있다.
 
해결책: Memo()
 
이를 도와줄 함수가 React.memo함수이다.
const MemorizedBtn = React.memo(Btn
이처럼 컴포넌트로 쓸거라 대문자로 변수를 먼저 만들고, memo의 인자에 사용자 컴포넌트를 넣어준다.
 
<MemorizedBtn text={value} onChangeValue={changeValue} />
<MemorizedBtn text="Continue" />
 
memo함수를 이용한 컴포넌트사용하면 setState가 실질적으로 rerendering 해야할 부분만 동작시켜준다.
 
<script type="text/babel">
function Btn(props) {
    console.log(`${props.text} is rendered`);
    return (
        <button
            onClick={props.onChangeValue}
            style={
                {
                    background: 'tomato',
                    color: 'white',
                    padding: '10px 20px',
                    border: 9,
                    borderRadius: 10,
                    fontSize: 16,
                }
            }
        >
            {props.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} onChangeValue={changeValue} />
            <MemorizedBtn text="Continue" />
        </div>
    );
}
const root = document.querySelector('#root');
ReactDOM.render(<App />, root);
</script>

정리: 

1. props에 function도 보낼 수 있다
이것은 JSX로 html 태그 자체에 이벤트 리스너를 넣는것과는 전혀 다른 것이다.
그저 이벤트를 실행시키는 함수가 프로퍼티로 들어간 것이다.
prop은 그냥 부모에서 자식으로 데이터를 넘길 때 사용하는 argument의 역할이니까!

2. (07:41~) 부모의 상태를 바꾸는 함수를 만들었고, 부모 컴포넌트에서 그 함수를 prop으로 보내면 자식 컴포넌트에서 그 함수가 실행된다.

3. 불필요한 re-render는 React.memo()로 관리할 수 있다
부모 컴포넌트의 state를 변경하면 당연히 그 자식 컴포넌트들도 Re-render가 일어남. 불필요한 렌더링이 발생할 수도 있는데, 이 경우에는 React.memo()로 prop의 변경이 일어난 부분만 렌더링 시킬 수 있음. 아주 많은 자식 컴포넌트를 가지고 있는 부모 컴포넌트일 때 사용하면 된다.

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

 

#4.2 Prop Types

 

정리
1. Prop 은 component 에 보내는 argument 이다.
2. PropType을 이용해서 보내는 prop 에 type을 정의 할수 있다.

정의하는 이유는 잘못된 type의 prop 이 보내지는 것을 방지하기 위해서다.

PropType을 정의 했을때 React는 에러메세지를 통해서 잘못된 type이 보내지고 있다고 알려준다.

추가적인 기능: OPTIONAL하지 않고 REQUIRED한 PROPS를 주고 싶은 경우 등등 (참고사이트 참고)
근데 타입스크립트를 쓴다면 더이상 필요 없다.

https://ko.reactjs.org/docs/typechecking-with-proptypes.html

 

PropTypes와 함께 하는 타입 검사 – React

A JavaScript library for building user interfaces

ko.reactjs.org

 

<body>
<div id="root"></div>
<!-- <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script> -->
<script src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
<!-- prop-types 적용 -->
<script src="https://unpkg.com/prop-types@15.7.2/prop-types.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
function Btn({ text, fontSize = 14 }) {
    return (
        <button
            style={
                {
                    background: 'tomato',
                    color: 'white',
                    padding: '10px 20px',
                    border: 9,
                    borderRadius: 10,
                    fontSize,
                }
            }
        >
            {text}
        </button>
    );
}

Btn.propTypes = {
    text: PropTypes.string,
    fontSize: PropTypes.number.isRequired,
};

function App() {
    return (
        <div>
            <Btn text="Save Changes" fontSize={20} />
            <Btn text="Continue" />
        </div>
    );
}
const root = document.querySelector('#root');
ReactDOM.render(<App />, root);
</script>
</body>