FrontEnd/React

동일한 패턴이 여러 컴포넌트에서 쓰이고 있다면? - React 고차 컴포넌트로 해결하기!

CoderHan 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

 

반응형