React study/React JS로 영화 웹 서비스 만들기

[React] 4-2. Prop-Types 알아보기

카누가 좋아요 2023. 5. 31. 00:25

📌 Props 더 살펴보기

버튼 안의 text를 바꾸는 ex)


function Btn({ text }) {
  return (
    <button
      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} onClick={changeValue} /> // 주목!
      <Btn text="Continue" big={false} />
    </div>
  );
}

위에서 onClick은 이벤트 리스너가 아닌 Btn 컴포넌트로 들어가는 prop이다.

이벤트 리스너로서의 역할을 하기 위해서는 Btn과 같은 커스텀 컴포넌트가 아닌 HTML element에다 넣어야 한다.

즉, Btn에 onClick을 속성으로 적어준다고 해서 그 버튼을 클릭을 하면 changeValue 함수가 실행되는 것이 아니다. 따라서 다른 prop을 작성하는 것과 똑같이 해야 한다.


function Btn({ text, onclick }) {
  return (
    <button
      onClick={onClick} // 주목! HTML button tag에서의 onClick은 이벤트 리스너이다. 옆에 실행될 함수 onClick에는 Btn 컴포넌트에 prop으로 들어간 onClick의 값인 changeValue 함수가 들어간다.
      style={{
        backgroundColor: "tomato",
        color: "white",
        padding: "10px 20px",
        border: 0,
        borderRadius: 10,
      }}
    >
      {text}
    </button>
  );
}

이제 Save Changes 버튼을 누르면 버튼 안의 text가 Revert Changes로 바뀐다.

기억해야 할 것은, 우리가 생성한 Btn에 props을 작성해 준다고 해서 그것이 자동적으로 return으로 들어가지는 않으므로 Btn 함수의 인자로 props를 작성해 주어야 한다.



다음과 같은 코드를 추가해 보자.


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

처음에 화면이 그려질 때 'Save Changes was rendered', 'Continue was rendered'가 console 창에 뜬다.

Save Changes 버튼을 누르면 changeValue 함수의 실행으로 App 컴포넌트에서의 state에 해당하는 value에 저장된 값이 Revert Changes로 변한다.

즉, Btn 컴포넌트의 부모 컴포넌트인 App 컴포넌트가 상태(state) 변경을 겪은 것이기 때문에 App 컴포넌트에서 다시 return되는 값이 화면에 그려지게 된다.

따라서 console 창에 'Revert Changes was rendered'와 'Continue was rendered' 문구가 뜨게 되고, 첫번째 버튼에서의 text도 Revert Changes로 변하게 된다.


그런데 위에서 Continue 버튼은 변화를 준 것이 없으므로 다시 render되지 않아도 된다.

이때, Memo(memorize의 의미)를 이용하여 React에게 props가 변경되지 않은 어떤 컴포넌트는 다시 그려지길 원치 않는다고 전달할 수 있다.


위에서 첫 번째 버튼의 props는 state와 연결되어 있기 때문에 첫 번째 버튼의 props는 바뀔 것이라는 것을 알 수 있다. 하지만 두 번째 버튼(Continue 버튼)의 props는 변하지 않는다.

따라서 다음과 같이 MemorizedBtn을 만들어 그것을 App 컴포넌트에서 return할 컴포넌트 명으로 사용한다.


const MemorizedBtn = React.memo(Btn);
// 주목! (Btn 컴포넌트를 React.memo()의 인자로 넣어주고, 아래에서 컴포넌트명을 MemorizedBtn으로 사용함으로써 props의 변화가 없는 컴포넌트는 다시 렌더링하지 않게 하였다.)
function App() {
  const [value, setValue] = React.useState("Save Changes");
  const changeValue = () => setValue("Revert Changes");
  return (
    <div>
      <MemorizedBtn text={value} onClick={changeValue} /> // 주목!
      <MemorizedBtn text="Continue" big={false} /> // 주목!
    </div>
  );
}

아까처럼 부모 컴포넌트의 상태가 바뀌어서 아무런 변화가 없는 자식 컴포넌트까지도 모두 다시 render하게 되면 추후에 어플리케이션이 느려지는 원인이 될 수도 있다.