[React - 기초] Render Props

2022. 3. 18. 14:18·React/패스트캠퍼스
반응형

 1. Render Props

재사용의 한 방법이다. ( Composition, HOC, render props ... )

 

React 컴포넌트 간에 코드를 공유하기 위해 함수 props를 이용하는 간단한 기능이다. 

 

2. 사용 이유

class MouseTracker extends React.Component {
  constructor(props) {
    super(props);
    this.handleMouseMove = this.handleMouseMove.bind(this);
    this.state = { x: 0, y: 0 };
  }

  handleMouseMove(event) {
    this.setState({
      x: event.clientX,
      y: event.clientY
    });
  }

  render() {
    return (
      <div style={{ height: '100vh' }} onMouseMove={this.handleMouseMove}>
        <h1>Move the mouse around!</h1>
        <p>The current mouse position is ({this.state.x}, {this.state.y})</p>
      </div>
    );
  }
}

웹페이지에서 마우스 위치를 추적하는 로직이다. 

스크린 주위로 마우스 커서를 움직이면, 컴포넌트가 마우스의 (x,y) 좌표를 <p>에 나타낸다. 

 

이것을 재사용할 수 있게 만들려면 어떻게 해야할까? 

class Mouse extends React.Component {
  constructor(props) {
    super(props);
    this.handleMouseMove = this.handleMouseMove.bind(this);
    this.state = { x: 0, y: 0 };
  }

  handleMouseMove(event) {
    this.setState({
      x: event.clientX,
      y: event.clientY
    });
  }

  render() {
    return (
      <div style={{ height: '100vh' }} onMouseMove={this.handleMouseMove}>

        {/* ...하지만 <p>가 아닌 다른것을 렌더링하려면 어떻게 해야 할까요? */}
        <p>The current mouse position is ({this.state.x}, {this.state.y})</p>
      </div>
    );
  }
}

class MouseTracker extends React.Component {
  render() {
    return (
      <>
        <h1>Move the mouse around!</h1>
        <Mouse />
      </>
    );
  }
}

<Mouse> 컴포넌트가 마우스의 움직임 이벤트를 감지하고 위치를 저장하는 행위를 하게 만들었다. 

 

하지만 추가로 마우스 주변에 고양이 그림을 보여주는 <Cat> 컴포넌트를 추가할 경우엔 어떻게 해야할까?

class Cat extends React.Component {
  render() {
    const mouse = this.props.mouse;
    return (
      <img src="/cat.jpg" style={{ position: 'absolute', left: mouse.x, top: mouse.y }} />
    );
  }
}

class MouseWithCat extends React.Component {
  constructor(props) {
    super(props);
    this.handleMouseMove = this.handleMouseMove.bind(this);
    this.state = { x: 0, y: 0 };
  }

  handleMouseMove(event) {
    this.setState({
      x: event.clientX,
      y: event.clientY
    });
  }

  render() {
    return (
      <div style={{ height: '100vh' }} onMouseMove={this.handleMouseMove}>

        {/*
          여기서 <p>를 <Cat>으로 바꿀 수 있습니다. ... 그러나 이 경우
          Mouse 컴포넌트를 사용할 때 마다 별도의 <MouseWithSomethingElse>
          컴포넌트를 만들어야 합니다, 그러므로 <MouseWithCat>는
          아직 정말로 재사용이 가능한게 아닙니다.
        */}
        <Cat mouse={this.state} />
      </div>
    );
  }
}

class MouseTracker extends React.Component {
  render() {
    return (
      <div>
        <h1>Move the mouse around!</h1>
        <MouseWithCat />
      </div>
    );
  }
}

<Mouse> 컴포넌트 안에 <Cat> 컴포넌트를 넣어 새로운 컴포넌트를 만들었다. 

원하는 목표는 달성했지만 <Mouse> 컴포넌트가 언제든지 마우스 위치만을 추적할 수 있게 캡슐화는 못하였다. 

 

오직 마우스 위치만 추적할 수 있는 <Mouse> 컴포넌트와 주변에 고양이를 그리는 <Cat> 컴포넌트를 캡슐화를 하면서

사용할 때 Render Props가 사용된다. 

 

3. 사용하기 

class Cat extends React.Component {
  render() {
    const mouse = this.props.mouse;
    return (
      <img src="/cat.jpg" style={{ position: 'absolute', left: mouse.x, top: mouse.y }} />
    );
  }
}

class Mouse extends React.Component {
  constructor(props) {
    super(props);
    this.handleMouseMove = this.handleMouseMove.bind(this);
    this.state = { x: 0, y: 0 };
  }

  handleMouseMove(event) {
    this.setState({
      x: event.clientX,
      y: event.clientY
    });
  }

  render() {
    return (
      <div style={{ height: '100vh' }} onMouseMove={this.handleMouseMove}>

        {/*
          <Mouse>가 무엇을 렌더링하는지에 대해 명확히 코드로 표기하는 대신,
          `render` prop을 사용하여 무엇을 렌더링할지 동적으로 결정할 수 있습니다.
        */}
        {this.props.render(this.state)}
      </div>
    );
  }
}

class MouseTracker extends React.Component {
  render() {
    return (
      <div>
        <h1>Move the mouse around!</h1>
        <Mouse render={mouse => (
          <Cat mouse={mouse} />
        )}/>
      </div>
    );
  }
}

이제 <Mouse> 컴포넌트는 오직 마우스의 위치만 추적하고 부모로부터 받은 render를 화면에 출력해주는 기능을 한다. 

그리고 <Cat> 컴포넌트도 <Mouse> 컴포넌트 안에서 호출되는 것이 아닌, 부모에서 호출되여 넘겨주는 방식이다. 

 

즉, render props는 무엇을 렌더링할지 컴포넌트에 알려주는 함수이다. 

 

반응형
저작자표시 비영리 변경금지 (새창열림)

'React > 패스트캠퍼스' 카테고리의 다른 글

[React - 기초] Reconciliation  (0) 2022.03.21
[React - 기초] PropTypes  (2) 2022.03.19
[React - 기초] Portals  (2) 2022.03.17
[React - 기초] Memoization  (2) 2022.03.15
[React - 기초] Hooks  (0) 2022.03.10
'React/패스트캠퍼스' 카테고리의 다른 글
  • [React - 기초] Reconciliation
  • [React - 기초] PropTypes
  • [React - 기초] Portals
  • [React - 기초] Memoization
잉여개발자
잉여개발자
풀스택 개발자를 목표로 잉여롭게 개발 공부도 하면서 다양한 취미 생활도 즐기고 있는 잉여 개발자입니다.
  • 잉여개발자
    잉여로운 개발일지
    잉여개발자
    • 분류 전체보기 (789)
      • 개발정보 (36)
      • 개발환경 (7)
      • 개발생활 (19)
      • React (141)
        • 이론 (23)
        • 기능 (12)
        • 실험실 (88)
        • 버그 (6)
        • 패스트캠퍼스 (9)
        • Npm (3)
      • React Native (28)
        • 공통 (6)
        • TypeScript (3)
        • JavaScript (18)
        • 버그 (1)
      • Next.js (30)
        • 이론 (13)
        • 실험실 (13)
        • 버그 (3)
      • Web (35)
      • 알고리즘 (202)
        • 풀이 힌트 (39)
      • JavaScript (47)
      • TypeScript (29)
        • 기초 (27)
        • 실험실 (2)
      • Node.js (13)
        • 이론 (0)
        • 기능 (3)
        • 실험실 (9)
        • 버그 (1)
      • 도커 (4)
      • CCNA (22)
        • 이론 (4)
        • 문제 (18)
      • 취미생활 (167)
        • 잉여로운 칵테일 (2)
        • 잉여의 식물키우기 (130)
        • 잉여로운 여행기 (11)
        • 잉여의 제2외국어 (21)
        • 잉여로운 책장 (2)
      • Java (1)
        • Java의 정석 (1)
      • 꿀팁 공유 (3)
  • 태그

    바질
    Docker
    식물
    바질 키우기
    영어회화
    webpack
    네트워크
    리얼클래스
    덤프
    프로그래머스
    타일러영어
    ChatGPT
    리액트
    next.js
    다이소
    redux
    리얼학습일기
    CCNA
    타입스크립트
    javascript
    CSS
    자바스크립트
    알고리즘
    Node.js
    영어독학
    Babel
    typescript
    네이버 부스트캠프
    react
    ReactNative
  • hELLO· Designed By정상우.v4.10.1
잉여개발자
[React - 기초] Render Props
상단으로

티스토리툴바