We want to hear from you!Take our 2021 Community Survey!
This site is no longer updated.Go to react.dev

Yüksək Dərəcəli Komponentlər

These docs are old and won’t be updated. Go to react.dev for the new React docs.

Higher-order components are not commonly used in modern React code.

Yüksək dərəcəli komponentlər (Higher-Order Component, HOC) React-də komponent məntiqini yenidən istifadə etmənin qabaqcıl texnikasıdır. HOC-lər özlüyündə React API-ın bir parçası deyil, React-in kompozisiyalı təbiətindən ortaya çıxan modeldir.

Qısacası, yüksək dərəcəli komponent bir komponenti parametr olaraq qəbul edib, yeni bir komponent qaytaran funksiyadır.

const EnhancedComponent = higherOrderComponent(WrappedComponent);

Adi komponent propları UI-a çevirir, yüksək dərəcəli komponent isə komponenti başqa bir komponentə çevirir.

HOC-lər üçüncü tərəf React kitabxanalarında yayğındır, məsələn Redux-ın connect-i və ya Relay-in createFragmentContainer-i kimi.

Bu sənəddə yüksək dərəcəli komponentlərin niyə faydalı olduğunu və necə yazılacağını müzakirə edəcəyik.

HOC-lərin Cross-Cutting Concern-lər Üçün İstifadəsi

Qeyd

Əvvəllər cross-cutting concern-ləri ələ almaq üçün mixin-ləri təklif etdik. İndi isə, mixin-lərin xeyirindən daha çox ziyanı olduğunu anladıq. Mixin-ləri niyə ləğv etdiyimiz və mövcud komponentlərinizi necə dəyişə biləcəyiniz haqqında buradan oxuyun.

Komponentlər React-də kodu yenidən istifadə etmənin əsasıdır. Ancaq, bəzi problemlərin ənənəvi komponentlərlə həll oluna bilmədiyini görəcəyik.

Məsələn, gəlin xarici mənbədən aldığı yorumlar siyahısını render edən CommentList komponentinə baxaq:

class CommentList extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.state = {
      // "DataSource" qlobal məlumatlar mənbəyidir
      comments: DataSource.getComments()
    };
  }

  componentDidMount() {
    // Dəyişikliklərə abunə olma
    DataSource.addChangeListener(this.handleChange);
  }

  componentWillUnmount() {
    // Dinləyicini təmizləmə
    DataSource.removeChangeListener(this.handleChange);
  }

  handleChange() {
    // Məlumat mənbəyi dəyişdikdə komponentin state-i yenilənir
    this.setState({
      comments: DataSource.getComments()
    });
  }

  render() {
    return (
      <div>
        {this.state.comments.map((comment) => (
          <Comment comment={comment} key={comment.id} />
        ))}
      </div>
    );
  }
}

İndi isə, bənzər formada, tək bloq yazısına abunə olan yeni komponent yazaq:

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

CommentListBlogPost eyni deyil — DataSource üzərində müxtəlif metodları çağırırlar və müxtəlif nəticələri render edirlər. Ancaq, əksər hissələri oxşardır:

  • Mount zamanı dəyişiklik dinləyicisini DataSource-a əlavə edir.
  • Məlumat qaynağı dəyişdikdə dinləyici içərisindən setState-i çağırır.
  • Unmount zamanı dəyişiklik dinləyicisini silir.

Təsəvvür edin ki, böyük bir applikasiyada DataSource-a abunə olma və setState-i çağırma dəsti hər dəfə təkrarlanacaq. Bizə bu məntiqin bir yerdə müəyyən edərək, bir çox komponent arasında istifadəyə imkan verən abstraksiya lazımdır. Burada yüksək dərəcəli komponentlər üzə çıxır.

CommentListBlogPost kimi komponentləri birbaşa yazmaq yerinə, bunları yaradan və DataSource-a abunə edən funksiya yaza bilərik. Bu funksiya abunə olduğu məlumatı prop kimi qəbul edən uşaq komponentini arqument kimi qəbul edəcək. Gəlin bu funksiyanı withSubscription adlandıraq:

const CommentListWithSubscription = withSubscription(
  CommentList,
  (DataSource) => DataSource.getComments()
);

const BlogPostWithSubscription = withSubscription(
  BlogPost,
  (DataSource, props) => DataSource.getBlogPost(props