ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 동일한 패턴이 여러 컴포넌트에서 쓰이고 있다면? - React 고차 컴포넌트로 해결하기!
    FrontEnd/React 2023. 1. 1. 23:05
    반응형

    고차 컴포넌트란?

    "고차 컴포넌트는 컴포넌트를 가져와 새 컴포넌트를 반환하는 함수이다."라고 공식 홈페이지에서 정의하고 있다.

     

    규모가 큰 애플리케이션에서 DataSouce에 접근하여 SetState를 호출하는 동일한 패턴이 반복적으로 발생할 때 유용하다.

     

    class CommentList extends React.Component {
      constructor(props) {
        super(props);
        this.handleChange = this.handleChange.bind(this);
        this.state = {
          // "DataSource" 는 글로벌 데이터 소스입니다.
          comments: DataSource.getComments()
        };
      }
    
      componentDidMount() {
        // 변화감지를 위해 리스너를 추가합니다.
        DataSource.addChangeListener(this.handleChange);
      }
    
      componentWillUnmount() {
        // 리스너를 제거합니다.
        DataSource.removeChangeListener(this.handleChange);
      }
    
      handleChange() {
        // 데이터 소스가 변경될때 마다 comments를 업데이트합니다.
        this.setState({
          comments: DataSource.getComments()
        });
      }
    
      render() {
        return (
          <div>
            {this.state.comments.map((comment) => (
              <Comment comment={comment} key={comment.id} />
            ))}
          </div>
        );
      }
    }
    
    //--------------------------------
    
    class BlogPost extends React.Component {
      constructor(props) {
        super(props);
        this.handleChange = this.handleChange.bind(this);
        this.state = {
          blogPost: DataSource.getBlogPost(props.id)
        };
      }
    
      componentDidMount() {
        DataSource.addChangeListener(this.handleChange);
      }
    
      componentWillUnmount() {
        DataSource.removeChangeListener(this.handleChange);
      }
    
      handleChange() {
        this.setState({
          blogPost: DataSource.getBlogPost(this.props.id)
        });
      }
    
      render() {
        return <TextBlock text={this.state.blogPost} />;
      }
    }

     

    위 두 컴포넌트는 DataSouce에 접근하여 DataSource.getBlogPost, DataSource.getComments를 이용해

    State를 설정한다.하는 일은 다르지만 비슷한 패턴으로 작성되었으므로 이를 위한 추상화가 필요하다.

     

    const CommentListWithSubscription = withSubscription(
      CommentList,
      (DataSource) => DataSource.getComments()
    );
    
    const BlogPostWithSubscription = withSubscription(
      BlogPost,
      (DataSource, props) => DataSource.getBlogPost(props.id)
    );

    이런식으로 withSubscription이라는 일반함수를 통해 두 컴포넌트를 구성했다.

     

    / 이 함수는 컴포넌트를 매개변수로 받고..
    function withSubscription(WrappedComponent, selectData) {
      // ...다른 컴포넌트를 반환하는데...
      return class extends React.Component {
        constructor(props) {
          super(props);
          this.handleChange = this.handleChange.bind(this);
          this.state = {
            data: selectData(DataSource, props)
          };
        }
    
        componentDidMount() {
          // ... 구독을 담당하고...
          DataSource.addChangeListener(this.handleChange);
        }
    
        componentWillUnmount() {
          DataSource.removeChangeListener(this.handleChange);
        }
    
        handleChange() {
          this.setState({
            data: selectData(DataSource, this.props)
          });
        }
    
        render() {
          // ... 래핑된 컴포넌트를 새로운 데이터로 랜더링 합니다!
          // 컴포넌트에 추가로 props를 내려주는 것에 주목하세요.
          return <WrappedComponent data={this.state.data} {...this.props} />;
        }
      };
    }

    withSubscription함수는 래핕된 컴포넌트를 새로운 데이터로 렌더링하는 것이 특징이다!

     

    래핑된 컴포넌트는 새로운 props, data와 함께 컨테이너의 모든 props를 전달받고, 이 데이터는 출력에 사용됩니다.

     

    이런식으로 코드의 재사용성을 높일 수 있습니다.

     

    자세한 내용은 공식홈페이지를 참고하세요!

    https://ko.reactjs.org/docs/higher-order-components.html

     

    고차 컴포넌트 – React

    A JavaScript library for building user interfaces

    ko.reactjs.org

     

    반응형

    댓글

Designed by Tistory.