ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • React #3. 컴포넌트의 prop 전달
    프론트/React 2024. 8. 4. 22:18

    컴포넌트를 재사용하고 효율적인 사용방법을 알아보자

     

    아래의 코드는 동일한 스타일을 가진 버튼을 SaveBtn, ConfirmBtn 컴포넌트로 복사 붙여넣기 한 후 텍스트만 변경한 코드이다. 아쉬운점은 스타일을 그대로 복사 붙여넣기 해서 나중에 고치기도 매우 불편하다. 왜냐하면 배경색을 토마토가 아닌 바나나로 바꾼다고 하면 하나하나 찾아가면서 바꾸어줘야한다.

            function SaveBtn() {
                return <button style={{
                    backgroundColor : "tomato",
                    color : "white",
                    padding : "10px 20px",
                    border : "0",
                    borderRadius : 10
                }}>Save Change</button>;
            }
    
            function ConfirmBtn() {
                return <button style={{
                    backgroundColor : "tomato",
                    color : "white",
                    padding : "10px 20px",
                    border : "0",
                    borderRadius : 10
                }}>Confirm</button>;
            }
    
            function App() {
                return (
                    <div>
                        <SaveBtn />
                        <ConfirmBtn />
                    </div>            
                );
            }

    그래서 하나의 컴포넌트에서 만드는 대신에 텍스트만 수정할 수 있도록 리팩토링 해보았다. JSX 에서 <Btn /> 컴포넌트를 실제로 함수이다. 그리고 컴포넌트에 안에 들어간 속성은 Btn 함수의 첫번째 인자에 Key-Value 형태로 들어가게 되어 같은 컴포넌트여도 속성이 다르므로 동적으로 렌더링할 수 있게 된다.

     

            function Btn({text}) {
                console.log({text})
                return <button style={{
                    backgroundColor : "tomato",
                    color : "white",
                    padding : "10px 20px",
                    border : "0",
                    borderRadius : 10
                }}>{text}</button>;
            }

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

     

    Btn 함수의 첫번째 인자가 오브젝트인것을 이미 알고 있으므로 { key 값 } 을 넣게 되면 props.text 하지 않아도 {key} 으로 간편하게 접근할 수 있다. 이를 통해서 알 수 있는 것은 props 에 들어가는 값은 첫번째 인자로 key value 형태로 들어가게 된다는것이다. 

     

            function Btn(props) {
                console.log(props)
                return <button
                    onClick={props.changeValue}
                    style={{
                    backgroundColor : "tomato",
                    color : "white",
                    padding : "10px 20px",
                    border : "0",
                    borderRadius : 10
                }}>{props.text}</button>;
            }

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

     

    여기서 주의할 점은 컴포넌트에 이벤트 리스너를 달아놔도 그거는 하나의 prop 일뿐 작동하지 않는다. 아래 사진 처럼 함수로만 들어가게 되지 이벤트는 직접 컴포넌트 안에 있는 태그에 걸어놔야한다.

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

     

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

     

    prop 을 전달할때 어떤 타입으로 보내줘야할지 다른 동료 개발자를 모를 수 있기 때문에

    prop-types 라이브러리로 아래의 코드를 적어주면 해당 컴포넌트의 prop 타입을 강제할 수 있고, 컴파일러 단계에서 타입이 다를 경우 경고 메시지를 보여준다.

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

Designed by Tistory.