>  기사  >  웹 프론트엔드  >  React 고차 컴포넌트 예제 분석

React 고차 컴포넌트 예제 분석

小云云
小云云원래의
2018-05-26 11:51:362172검색

이 글은 주로 React 고차 컴포넌트에 대한 심층적인 이해를 제공합니다. React 고차 컴포넌트에 대해 좀 더 명확하게 이해하시기 바랍니다.

1. React에서 HOC(고차 컴포넌트)는 컴포넌트 로직을 재사용하기 위한 고급 기술입니다. HOC는 React API의 일부가 아닙니다. HOC는 구성 요소를 가져와서 새 구성 요소를 반환하는 함수입니다. React에서 컴포넌트는 코드 재사용의 기본 단위입니다.

2. HOC를 설명하려면 다음 두 가지 예를 들어보세요.

CommentList 구성 요소는 주석 목록을 렌더링하고 목록의 데이터는 외부 소스에서 가져옵니다.

class CommentList extends React.Component {

  constructor() {

   super();

   this.handleChange = this.handleChange.bind(this);

   this.state = {

    // "DataSource" is some global data source

    comments: DataSource.getComments()

   };

  }

 

  componentDidMount() {

   // Subscribe to changes

   DataSource.addChangeListener(this.handleChange);

  }

 

  componentWillUnmount() {

   // Clean up listener

   DataSource.removeChangeListener(this.handleChange);

  }

 

  handleChange() {

   // Update component state whenever the data source changes

   this.setState({

    comments: DataSource.getComments()

   });

  }

 

  render() {

   return (

    <p>

     {this.state.comments.map((comment) => (

      <Comment comment={comment} key={comment.id} />

     ))}

    </p>

   );

  }

 }

다음은 블로그 정보를 표시하는 데 사용되는 BlogPost 컴포넌트입니다.

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} />;

  }

 }

두 컴포넌트는 서로 다르며 DataSource의 다른 메소드를 호출하고 출력도 다르지만 그 중 대부분의 구현은 동일합니다. :

1. 로딩이 완료된 후 DataSource에 변경 리스너를 추가합니다
2. 데이터 소스가 변경되면 리스너 내부에서 setState를 호출합니다. 3. 제거 후 변경 리스너를 제거합니다

애플리케이션에서는 DataSource에 액세스하고 setState를 호출하는 동일한 패턴이 계속해서 발생합니다. 우리는 이 논리를 한 곳에서만 정의한 다음 여러 구성 요소에서 공유할 수 있도록 이 프로세스를 추상화하려고 합니다.

다음으로 구성 요소를 생성하는 함수를 작성합니다. 이 함수는 두 개의 매개 변수를 받아들이는데, 그 중 하나는 구성 요소이고 다른 하나는 함수입니다. 아래에서는 withSubscription 함수가 호출됩니다

const CommentListWithSubscription = withSubscription(

 CommentList,

 (DataSource) => DataSource.getComments()

);

 

const BlogPostWithSubscription = withSubscription(

 BlogPost,

 (DataSource, props) => DataSource.getBlogPost(props.id)

);

withSubscription 호출 시 전달되는 첫 번째 매개변수는 래핑된 컴포넌트이고, 두 번째 매개변수는 데이터를 검색하는 데 사용되는 함수입니다.


CommentListWithSubscription 및 BlogPostWithSubscription이 렌더링되면 CommentList 및 BlogPost는 DataSource에서 현재 검색된 데이터를 저장하는 data라는 prop을 허용합니다. withSubscription 코드는 다음과 같습니다:

// This function takes a component...

function withSubscription(WrappedComponent, selectData) {

 // ...and returns another component...

 return class extends React.Component {

  constructor(props) {

   super(props);

   this.handleChange = this.handleChange.bind(this);

   this.state = {

    data: selectData(DataSource, props)

   };

  }

 

  componentDidMount() {

   // ... that takes care of the subscription...

   DataSource.addChangeListener(this.handleChange);

  }

 

  componentWillUnmount() {

   DataSource.removeChangeListener(this.handleChange);

  }

 

  handleChange() {

   this.setState({

    data: selectData(DataSource, this.props)

   });

  }

 

  render() {

   // ... and renders the wrapped component with the fresh data!

   // Notice that we pass through any additional props

   return <WrappedComponent data={this.state.data} {...this.props} />;

  }

 };

}

HOC는 입력 구성 요소를 수정하지 않으며 상속을 사용하여 동작을 재사용하지도 않습니다. HOC는 단지 함수일 뿐입니다. 래핑된 구성 요소는 컨테이너의 모든 prop을 허용하고 래핑된 구성 요소의 출력을 렌더링하는 데 사용되는 새 prop(데이터)도 허용합니다. HOC는 데이터가 어떻게 사용되는지, 왜 데이터가 사용되는지 신경 쓰지 않으며 래핑된 구성 요소는 데이터를 어디서 가져오는지 신경 쓰지 않습니다.


withSubscription은 일반적인 기능이므로 매개변수를 원하는 만큼 추가할 수 있습니다. 예를 들어, 래핑된 구성 요소에서 HOC를 추가로 격리하기 위해 데이터 속성의 이름을 구성 가능하게 만들 수 있습니다.


shouldComponentUpdate 구성을 수락하거나 데이터 소스의 매개변수를 구성하세요.

고차 컴포넌트를 사용할 때 주의해야 할 사항이 몇 가지 있습니다.

1. 원본 컴포넌트를 수정하지 마세요. 이것은 매우 중요합니다.

다음과 같은 예가 있습니다:

function logProps(InputComponent) {

 InputComponent.prototype.componentWillReceiveProps = function(nextProps) {

  console.log(&#39;Current props: &#39;, this.props);

  console.log(&#39;Next props: &#39;, nextProps);

 };

 // The fact that we&#39;re returning the original input is a hint that it has

 // been mutated.

 return InputComponent;

}

 

// EnhancedComponent will log whenever props are received

const EnhancedComponent = logProps(InputComponent);

여기에는 몇 가지 문제가 있습니다. 1. 가져온 컴포넌트는 향상된 컴포넌트와 별도로 재사용할 수 없습니다. 2. EnhancedComponent에 다른 HOC를 적용하면 componentWillReceiveProps도 변경됩니다.


함수 유형 구성 요소에는 수명 주기가 없기 때문에 이 HOC는 함수 유형 구성 요소에 적용할 수 없습니다. 함수 HOC는 수정 대신 입력 구성 요소를 컨테이너 구성 요소로 래핑하여 구성을 사용해야 합니다.

function logProps(WrappedComponent) {

 return class extends React.Component {

  componentWillReceiveProps(nextProps) {

   console.log(&#39;Current props: &#39;, this.props);

   console.log(&#39;Next props: &#39;, nextProps);

  }

  render() {

   // Wraps the input component in a container, without mutating it. Good!

   return <WrappedComponent {...this.props} />;

  }

 }

}

이 새로운 logProps는 이전 logProps와 동일한 기능을 가지고 있지만 새로운 logProps는 잠재적인 충돌을 방지합니다. 클래스 유형 구성 요소와 함수 유형 구성 요소에도 동일하게 적용됩니다.

2. 렌더링 메서드에 HOC를 사용하지 마세요

React의 diff 알고리즘은 구성 요소의 ID를 사용하여 기존 하위 트리를 업데이트할지 아니면 이전 하위 트리를 해체하고 렌더링에서 반환된 경우 새 하위 트리를 로드할지 결정합니다. 메소드 구성 요소가 이전에 렌더링된 구성 요소와 동일(===)하면 React는 diff 알고리즘을 통해 이전에 렌더링된 구성 요소를 업데이트합니다. 그렇지 않으면 이전에 렌더링된 하위 트리가 완전히 언로드됩니다.

render() {

 // A new version of EnhancedComponent is created on every render

 // EnhancedComponent1 !== EnhancedComponent2

 const EnhancedComponent = enhance(MyComponent);

 // That causes the entire subtree to unmount/remount each time!

 return <EnhancedComponent />;

}

결과 구성 요소가 한 번만 생성되도록 구성 요소 정의 외부에서 HOC를 사용하세요. 몇몇 경우에는 HOC를 동적으로 적용해야 하며, 라이프 사이클 함수나 생성자에서 이를 수행해야 합니다.

3. 정적 메서드는 수동으로 복사해야 합니다.

때때로 React 구성 요소에 정적 메서드를 정의하는 것이 매우 유용합니다. 컴포넌트에 HOC를 적용하면 원래 컴포넌트가 컨테이너 컴포넌트에 래핑되더라도 반환된 새 컴포넌트에는 원래 컴포넌트의 정적 메서드가 없습니다.

// Define a static method

WrappedComponent.staticMethod = function() {/*...*/}

// Now apply an HOC

const EnhancedComponent = enhance(WrappedComponent);

 

// The enhanced component has no static method

typeof EnhancedComponent.staticMethod === &#39;undefined&#39; // true

반환된 구성 요소가 원본 구성 요소의 정적 메서드를 가지려면 함수 내부에서 원본 구성 요소의 정적 메서드를 새 구성 요소에 복사해야 합니다.


function enhance(WrappedComponent) {

 class Enhance extends React.Component {/*...*/}

 // Must know exactly which method(s) to copy :(

  // 你也能够借助第三方工具

 Enhance.staticMethod = WrappedComponent.staticMethod;

 return Enhance;

}

4. 컨테이너 컴포넌트의 참조는 래핑된 컴포넌트로 전달되지 않습니다.

컨테이너 컴포넌트의 props는 래핑된 컴포넌트로 쉽게 전달될 수 있지만 컨테이너 컴포넌트의 참조는 전달되지 않습니다. 래핑된 구성 요소에. HOC를 통해 반환된 구성 요소에 대한 참조를 설정하면 이 참조는 래핑된 구성 요소가 아닌 가장 바깥쪽 컨테이너 구성 요소를 참조합니다.

관련 추천

React 고차 컴포넌트 소개 예시 공유

Vue 고차 컴포넌트 사용법

아주 간단한 예시를 통해 React.js 고차 컴포넌트의 개념을 이해해보세요

위 내용은 React 고차 컴포넌트 예제 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.