React 구성 요소 Render Props VS HOC 디자인 모드

10807 단어
React 의 디자인 모델 은 여러 가지 가 있 습 니 다. 예 를 들 어 무 상태 구성 요소 / 표현 형 구성 요소, 상태 구성 요소 / 용기 형 구성 요소, render 모드 구성 요소, 고급 구성 요소 등 이 있 습 니 다.본 고 는 주로 react 의 render 모델 과 HOC 디자인 모델 을 소개 하고 실제 사례 를 통 해 비교 하고 자 한다.
render props 모드
The Render Props 는 코드 를 반복 하지 않 고 구성 요소 간 기능 을 공유 하 는 방법 이다.다음 과 같다.
 (
  

Hello {data.target}

)}/>

prop 를 사용 하여 보 여 주 는 내용 을 정의 합 니 다. 구성 요 소 는 기능 만 주입 할 뿐 UI 에 어떻게 적용 되 는 지 알 필요 가 없습니다.render prop 모드 는 사용자 가 단독 구성 요 소 를 정의 하여 prop 방법 을 전달 하여 공유 구성 요소 가 돌아 와 야 할 내용 을 표시 하 는 것 을 의미 합 니 다.
Render Props 의 핵심 사상 은 하나의 함 수 를 통 해 class 구성 요소 의 state 를 props 로 순수 함수 구성 요소 에 전달 하 는 것 이다.
import React from 'react';

const SharedComponent extends React.Component {
  state = {...}
  render() {
    return (
      
{this.props.render(this.state)}
); } } export default SharedComponent;
this.props.render() 는 다른 구성 요소 에 의 해 전달 되 었 다.위 구성 요 소 를 사용 하기 위해 서 다음 작업 을 진행 할 수 있 습 니 다.
import React from 'react';
import SharedComponent from 'components/SharedComponent';

const SayHello = () => (
   (
    hello!,{...state}
  )} />
);

{this. props. render (this. state)} 이 함 수 는 state 를 매개 변수 로 props. render 방법 에 전달 하고 호출 할 때 구성 요소 에 필요 한 state 를 직접 가 져 오 면 됩 니 다.render props 모드 에서 가장 중요 한 것 은 react 요 소 를 되 돌려 주 는 것 입 니 다. 예 를 들 어 제 가 위의 render 속성 을 바 꾸 는 것 은 유효 합 니 다.
import React from 'react';

const SharedComponentWithGoofyName extends React.Component {
  render() {
    return (
      
{this.props.wrapThisThingInADiv()}
); } } const SayHelloWithGoofyName = () => ( ( hello! )} /> );

HOC 디자인 모드
React 의 고급 구성 요 소 는 코드 를 반복 하지 않 고 구성 요소 간 에 유 니 버 설 기능 을 공유 하 는 모드 (즉 DRY 모드) 에 사 용 됩 니 다.
고급 구성 요 소 는 실제 함수 입 니 다.HOC 함 수 는 구성 요 소 를 매개 변수 로 하고 새로운 구성 요 소 를 되 돌려 줍 니 다.구성 요 소 를 다른 구성 요소 로 변환 하고 추가 데이터 나 기능 을 추가 합 니 다.
고급 구성 요 소 는 React 생태 체인 기술 에서 자주 사용 되 고 독자 에 게 익숙 하 다. 예 를 들 어 Redux 중의 connect, React Router 중의 withRouter 등 이다.
흔히 볼 수 있 는 고급 구성 요 소 는 다음 과 같다.
import React from 'react';

const withSecretToLife = (WrappedComponent) => {
  class HOC extends React.Component {
    render() {
      return (
        
      );
    }
  }
    
  return HOC;
};

export default withSecretToLife;

secretToLife 가 42 인 것 을 알 고 있 습 니 다. 이 정 보 를 공유 해 야 할 구성 요소 가 있 습 니 다. 이 때 SecretToLife 의 HOC 를 만 들 고 prop 로 우리 에 게 전달 하 는 구성 요소 입 니 다.
import React from 'react';
import withSecretToLife from 'components/withSecretToLife';

const DisplayTheSecret = props => (
  
The secret to life is {props.secretToLife}.
); const WrappedComponent = withSecretToLife(DisplayTheSecret); export default WrappedComponent;

이 때 Wrapped Component 는 DisplayTheSecret 의 증강 버 전 일 뿐 secretToLife 속성 에 접근 할 수 있 습 니 다.
Render Props 와 HOC 모드 인 스 턴 스 비교
본 고 는 localStorage API 를 이용 한 작은 예 로 각각 HOC 디자인 모델 과 The Render Props 디자인 모델 로 demo 를 작성 하고 자 한다.
HOC Example
import React from 'react';

const withStorage = (WrappedComponent) => {
  class HOC extends React.Component {
    state = {
      localStorageAvailable: false, 
    };
  
    componentDidMount() {
       this.checkLocalStorageExists();
    }
  
    checkLocalStorageExists() {
      const testKey = 'test';

      try {
          localStorage.setItem(testKey, testKey);
          localStorage.removeItem(testKey);
          this.setState({ localStorageAvailable: true });
      } catch(e) {
          this.setState({ localStorageAvailable: false });
      } 
    }
  
    load = (key) => {
      if (this.state.localStorageAvailable) {
        return localStorage.getItem(key); 
      }
      
      return null;
    }
    
    save = (key, data) => {
      if (this.state.localStorageAvailable) {
        localStorage.setItem(key, data);
      }
    }
    
    remove = (key) => {
      if (this.state.localStorageAvailable) {
        localStorage.removeItem(key);
      }
    }
    
    render() {
      return (
        
      );
    }
  }
    
  return HOC; 
}

export default withStorage;

withStorage 에서 componentDidMount 생명주기 함 수 를 사용 하여 LocalStorageExists 함수 에 localStorage 가 존재 하 는 지 확인 합 니 다.
local, save, remove 는 localStorage 를 조작 하 러 왔 습 니 다.현재 HOC 구성 요소 에 감 싸 서 관련 정 보 를 표시 할 새 구성 요 소 를 만 듭 니 다.정 보 를 얻 는 API 호출 은 시간 이 오래 걸 리 기 때문에 이 값 들 이 설정 되면 변 하지 않 는 다 고 가정 할 수 있 습 니 다.저 희 는 이 API 호출 을 저장 하지 않 은 상태 에서 만 수행 합 니 다.그리고 사용자 가 페이지 로 돌아 갈 때마다 API 가 돌아 오 기 를 기다 리 는 것 이 아니 라 바로 데 이 터 를 방문 할 수 있 습 니 다.
import React from 'react';
import withStorage from 'components/withStorage';

class ComponentNeedingStorage extends React.Component {
  state = {
    username: '',
    favoriteMovie: '',
  }

  componentDidMount() {
    const username = this.props.load('username');
    const favoriteMovie = this.props.load('favoriteMovie');
    
    if (!username || !favoriteMovie) {
      // This will come from the parent component
      // and would be passed when we spread props {...this.props}
      this.props.reallyLongApiCall()
        .then((user) => {
          this.props.save('username', user.username) || '';
          this.props.save('favoriteMovie', user.favoriteMovie) || '';
          this.setState({
            username: user.username,
            favoriteMovie: user.favoriteMovie,
          });
        }); 
    } else {
      this.setState({ username, favoriteMovie })
    }
  }

  render() {
    const { username, favoriteMovie } = this.state;
    
    if (!username || !favoriteMovie) {
      return 
Loading...
; } return (
My username is {username}, and I love to watch {favoriteMovie}.
) } } const WrappedComponent = withStorage(ComponentNeedingStorage); export default WrappedComponent;

패 키 징 구성 요소 의 componentDidMount 내부 에서 먼저 localstorage 에서 가 져 오 려 고 시도 합 니 다. 존재 하지 않 으 면 비동기 로 호출 하여 얻 은 정 보 를 localstorage 에 저장 하고 표시 합 니 다.
The Render Props Exapmle
import React from 'react';

class Storage extends React.Component {
    state = {
      localStorageAvailable: false, 
    };
  
    componentDidMount() {
       this.checkLocalStorageExists();
    }
  
    checkLocalStorageExists() {
      const testKey = 'test';

      try {
          localStorage.setItem(testKey, testKey);
          localStorage.removeItem(testKey);
          this.setState({ localStorageAvailable: true });
      } catch(e) {
          this.setState({ localStorageAvailable: false });
      } 
    }
  
    load = (key) => {
      if (this.state.localStorageAvailable) {
        return localStorage.getItem(key); 
      }
      
      return null;
    }
    
    save = (key, data) => {
      if (this.state.localStorageAvailable) {
        localStorage.setItem(key, data);
      }
    }
    
    remove = (key) => {
      if (this.state.localStorageAvailable) {
        localStorage.removeItem(key);
      }
    }
    
    render() {
      return (
        
          this.props.render({
            load: this.load,
            save: this.save,
            remove: this.remove,
          })
        
      );
    } 
}

Storage 구성 요소 내 부 는 HOC 의 withStorage 와 유사 합 니 다. 다른 것 은 Storage 가 구성 요 소 를 매개 변수 로 받 아들 이지 않 고 this. props. render 를 되 돌려 줍 니 다.
import React from 'react';
import Storage from 'components/Storage';

class ComponentNeedingStorage extends React.Component {
  state = {
    username: '',
    favoriteMovie: '',
    isFetching: false,
  }

  fetchData = (save) => {
    this.setState({ isFetching: true });
    
    this.props.reallyLongApiCall()
      .then((user) => {
        save('username', user.username);
        save('favoriteMovie', user.favoriteMovie);

        this.setState({
          username: user.username,
          favoriteMovie: user.favoriteMovie,
          isFetching: false,
        });
      }); 
  }

  render() {
    return (
       {
          const username = load('username') || this.state.username;
          const favoriteMovie = load('favoriteMovie') || this.state.username;
      
          if (!username || !favoriteMovie) {
            if (!this.state.isFetching) {
              this.fetchData(save);               
            }

            return 
Loading...
; } return (
My username is {username}, and I love to watch {favoriteMovie}.
); }} /> ) } }

ComponentNeedingStorage 구성 요소 에 있어 Storage 구성 요소 의 render 속성 전달 세 가지 방법 을 이용 하여 일련의 데이터 조작 을 하여 관련 정 보 를 보 여 줍 니 다.
render props VS HOC 모드
전체적으로 보면 render props 는 고급 구성 요소 와 유사 합 니 다. Puru component 에 state 를 추가 하고 react 의 생명 주기 에 응답 하 는 것 입 니 다.HOC 모드 의 장점 은 다음 과 같다.
  • ES6
  • 지원
  • 재 활용 성 이 강하 고 HOC 는 순수 함수 이 며 반환 값 은 구성 요소 이 며 다 중 끼 워 넣 을 수 있 습 니 다
  • 여러 개의 매개 변 수 를 지원 하고 적용 범 위 를 강화 합 니 다
  • 물론 다음 과 같은 단점 도 있다.
  • 여러 개의 HOC 를 함께 사용 할 때 하위 구성 요소 의 props 가 어떤 HOC 가 전달 하 는 지 직접 판단 할 수 없다
  • 여러 구성 요소 가 내장 되 어 있어 같은 이름 의 props
  • 가 쉽게 생 긴 다.
  • HOC 는 많은 쓸모없는 구성 요 소 를 생 성하 여 구성 요소 의 등급 을 강화 할 수 있 습 니 다
  • Render Props 모델 의 등장 은 주로 HOC 에서 발생 하 는 문 제 를 해결 하기 위 한 것 이다.장점 은 다음 과 같다.
  • ES6
  • 지원
  • props 이름 문 제 는 걱정 하지 않 아 도 됩 니 다. render 함수 에서 필요 한 state
  • 만 가 져 옵 니 다.
  • 쓸모없는 구성 요소 에 심층 급
  • 이 발생 하지 않 습 니 다.
  • render props 모델 의 구축 은 모두 동적 이 고 모든 변 화 는 render 에서 촉발 되 며 구성 요소 안의 생명 주 기 를 더욱 잘 이용 할 수 있 습 니 다.

  • 물론 필 자 는 Render Props 와 HOC 두 가지 선택 에 대해 서로 다른 장면 에 따라 선택해 야 한다 고 생각한다.Render Props 모드 는 HOC 보다 직관 적 이 고 디 버 깅 에 도 유리 하 며 HOC 는 여러 개의 매개 변 수 를 입력 하여 많은 코드 량 을 줄 일 수 있 습 니 다.
    Render Props 는 화면의 스크롤 위치 나 마우스 위 치 를 추적 하 는 등 읽 기 전용 작업 에 매우 적합 합 니 다.HOC 는 상기 localstorage 기능 과 같은 더욱 복잡 한 조작 을 잘 수행 하 는 경향 이 있다.
    참고 문헌
    Understanding React Render Props by Example
    Understanding React Higher-Order Components by Example
    Ultimate React Component Patterns with Typescript 2.8
    React Component Patterns

    좋은 웹페이지 즐겨찾기