Введение в React Higher Order Components (HOC) 📖 и практика 💻

React.js
Введение в React Higher Order Components (HOC) 📖 и практика 💻

Предисловие ✍️

  • Как участник фронтенда Xiaobai, я никогда не был в контакте с высокоуровневыми компонентами React.Когда я впервые увидел название, я не понял его 😱, и даже имел представление «от входа до сдаваться".
  • Конечно 🦢, после глубокого изучения я обнаружил, что на самом деле это очень простая концепция, но она очень часто используется. Его функция заключается в реализации повторного использования кода и логической абстракции.stateиpropsВыполняйте абстракции и операции, уточняйте компоненты (например, добавляйте жизненные циклы), реализуйте перехват рендеринга и многое другое.
  • Из-за полезности компонентов более высокого порядка 💪 он часто используется большим количествомReact.jsСвязанные сторонние библиотеки, такие какReact-Redux(Для управления состоянием реагирующих приложений портал 👉Начало работы 📖 и настройка 👩🏾‍💻 Учебное пособие для Redux + React-router),React-Loadable(для загрузки компонентов более высокого порядка с динамически импортированными компонентами) и т. д.
  • Так много было введено, давайте перейдем к теме ниже и познакомим вас с высокоуровневыми компонентами простым способом, представив соответствующие базовые знания и практические сценарии 🐛.

Основная концепция компонентов высшего порядка (что это такое❓)

  • Компоненты более высокого порядка (HOC, Higher-Order Components) не являются компонентами, афункция, который принимает компонент в качестве параметра и возвращает новый обновленный компонент:
const EnhancedComponent = higherOrderComponent(WrappedComponent);
  • Следует различать, что компоненты будутpropsПреобразование в пользовательский интерфейс и компонент более высокого порядка — это преобразование компонента в другой компонент.
  • Компоненты более высокого порядка — это продвинутый метод повторного использования логики компонентов в React.Подробное описание его принципов см.официальная документация.

Причины использования компонентов высшего порядка (почему ❓)

  • В развитии бизнеса, хотя разработка проекта может быть завершена без освоения высокоуровневых компонентов, если мы сможем гибко использовать высокоуровневые компоненты (дополнительный элемент 🥰), код проекта может стать более элегантным, а повторное использование кода может быть улучшено. и гибкость для повышения эффективности разработки.
  • В то же время понимание компонентов более высокого порядка во многом связано с нашим пониманием различныхReact.jsОбоснование сторонних библиотек полезно 👍.
  • Проблемы, которые могут решить компоненты более высокого порядка, можно просто свести к следующим трем аспектам:
    • Извлечение повторяющегося кода, реализация повторного использования компонентов, общий сценарий: повторное использование страницы.
    • Условный рендеринг, управление логикой рендеринга компонентов (перехват рендеринга), распространенные сценарии: контроль разрешений.
    • Захват/перехват жизненного цикла обрабатываемого компонента, общие сценарии: отслеживание производительности рендеринга компонентов, управление журналами.
  • Видно, что роль высокоуровневых компонентов очень велика 💪 Далее я представлю реализацию высокоуровневых компонентов, чтобы углубить ваше понимание роли высокоуровневых компонентов.

Реализация компонентов высшего порядка (как это сделать❓)

  • Как правило, существует два способа реализации компонентов более высокого порядка:
    • Реквизит Прокси
      • Возвращает функциональный компонент без состояния
      • возвращает компонент класса
    • Инверсия наследования
  • Различия в реализации компонентов более высокого порядка определяют соответствующие сценарии их применения:Reactкомпонент содержитprops,state,ref, методы жизненного цикла,staticМетоды иReactЕсть несколько важных частей дерева элементов, поэтому я буду сравнивать различия в реализации двух компонентов более высокого порядка со следующих аспектов:
    • Можно ли запаковать оригинальные компоненты?
    • Наследуется ли исходный компонент
    • Может читать/манипулировать исходным компонентомprops
    • Может читать/манипулировать исходным компонентомstate
    • может пройтиrefдоступ к оригинальному компонентуdomэлемент
    • Влиять ли на какой-то жизненный цикл и другие методы исходного компонента
    • Брать ли оригинальные комплектующиеstaticметод
    • Можете ли вы перехватить исходный метод жизненного цикла компонента?
    • Может отображать угон

Риелтером

  • Прокси свойств — это наиболее распространенная реализация, которая по существу использует композицию для реализации функциональности, заключая компоненты в компоненты-контейнеры.
  • Отношение жизненного цикла между компонентом более высокого порядка и исходным компонентом, реализованным методом прокси свойства, полностью является отношением жизненного цикла между родительским и дочерним компонентами React, поэтому компонент более высокого порядка, реализованный таким образом, повлияет на некоторый жизненный цикл. методы исходного компонента.

Реквизит для действий

  • Самый простой код реализации прокси свойства выглядит следующим образом:
// 返回一个无状态的函数组件
function HOC(WrappedComponent) {
  const newProps = { type: 'HOC' };
  return props => <WrappedComponent {...props} {...newProps}/>;
}

// 返回一个有状态的 class 组件
function HOC(WrappedComponent) {
  return class extends React.Component {
    render() {
      const newProps = { type: 'HOC' };
      return <WrappedComponent {...this.props} {...newProps}/>;
    }
  };
}
  • Как видно из приведенного выше кода, упакованный компонент компонента более высокого порядка, реализованный методом прокси атрибута, может перехватывать передаваемые от родительского компонента.props, заблаговременноpropsвыполнить некоторые операции, такие как добавлениеtypeАтрибуты.

абстрактное состояние

  • Следует отметить, что ⚠️ заключается в том, что компоненты более высокого порядка, реализованные с помощью метода прокси атрибута, не могут напрямую управлять исходными компонентами.state, но может бытьpropsи пара функций обратного вызоваstateАннотация. ️
  • Типичным примером является реализация неконтролируемого компонента дляУправляемые компонентыПреобразование:
// 高阶组件
function HOC(WrappedComponent) {
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        name: '',
      };
      this.onChange = this.onChange.bind(this);
    }
    
    onChange = (event) => {
      this.setState({
        name: event.target.value,
      })
    }
    
    render() {
      const newProps = {
        name: {
          value: this.state.name,
          onChange: this.onChange,
        },
      };
      return <WrappedComponent {...this.props} {...newProps} />;
    }
  };
}

// 使用
@HOC
class Example extends Component {
  render() {
    return <input name="name" {...this.props.name} />;
  }
}

Получить реф.

  • чтобы получить доступDOM element(focusсобытия, анимация, использование сторонних библиотек для манипулирования DOM), а иногда мы используемrefсвойства, оrefsДля ознакомления см.официальная документация.
  • refСвойства могут быть объявлены только для компонентов типа class, но не для компонентов типа function (поскольку у компонентов без состояния нет экземпляров).
  • Компоненты более высокого порядка, реализованные через прокси свойств, не могут напрямую получитьrefsссылка, но может быть передана в оригинальном компонентеrefВызов родительского компонента в функции обратного вызоваrefФункция обратного вызова для получения исходного компонентаrefsЦитировать.
  • Предположим, естьUserКомпонент (оригинальный компонент), его код выглядит следующим образом:
import * as React from 'react';
import * as styles from './index.module.less';

interface IProps {
  name: string;
  age: number;
  inputRef?: any;
}
class User extends React.Component<IProps> {
  private inputElement: any ;

  static sayHello () {
    console.error('hello world'); // tslint:disable-line
  }

  constructor (props: IProps) {
    super(props);
    this.focus = this.focus.bind(this);
    this.onChange = this.onChange.bind(this);
  }

  state = {
    name: '',
    age: 0,
  };

  componentDidMount () {
    this.setState({
      name: this.props.name,
      age: this.props.age,
    });
  }

  onChange = (e: any) => {
    this.setState({
      age: e.target.value,
    });
  }

  focus () {
    this.inputElement.focus();
  }

  render () {
    return (
      <div className={styles.wrapper}>
        <div className={styles.nameWrapper}>姓名:{this.state.name}</div>
        <div className={styles.ageWrapper}>
          年龄:
            <input
              className={styles.input}
              value={this.state.age}
              onChange={this.onChange}
              type="number"
              ref={input => {
                if (this.props.inputRef) {
                  this.props.inputRef(input); // 调用父组件传入的ref回调函数
                }
                this.inputElement = input;
              }}
            />
        </div>
        <div>
          <button
            className={styles.button}
            onClick={this.focus}
          >
            获取输入框焦点
          </button>
        </div>
      </div>
    );
  }
}

export default User;
  • Исходный компонент можно получить с помощью метода прокси свойстваrefsСсылочный код компонента более высокого порядка выглядит следующим образом:
import * as React from 'react';
import * as styles from './index.module.less';

function HOC (WrappedComponent: any) {
    let inputElement: any = null;

    function handleClick () {
      inputElement.focus();
    }

    function wrappedComponentStaic () {
      WrappedComponent.sayHello();
    }

    return (props: any) => (
      <div className={styles.hocWrapper}>
        <WrappedComponent
          inputRef={(el: any) => { inputElement = el; }}
          {...props}
        />
        <input
          type="button"
          value="获取子组件输入框焦点"
          onClick={handleClick}
          className={styles.focusButton}
        />
        <input
          type="button"
          value="调用子组件static"
          onClick={wrappedComponentStaic}
          className={styles.callButton}
        />
      </div>
    );
}

export default HOC;
  • использовать:
import React from 'react';
import HOC from '../../components/OperateRefsHOC';
import User from '../../components/User';

const EnhanceUser = HOC(User);

class OperateRefs extends React.Component<any> {
  render () {
    return <EnhanceUser name="小明" age={12} />;
  }
}

export default OperateRefs;
  • После обертывания компонентами более высокого порядкаEnhanceUserкомпоненты могут быть доступныUserв компонентеinputэлемент:

Получить статический метод исходного компонента

  • Когда обрабатываемый компонент является компонентом класса, компонент более высокого порядка, реализованный через прокси свойства (независимо от того, возвращает ли он функциональный компонент Или вернуть компонент класса, оба) вы можете получить статический метод исходного компонента, такой как код компонента высокого порядка, приведенный выше, основной код выглядит следующим образом:
import * as React from 'react';
import * as styles from './index.module.less';

function HOC (WrappedComponent: any) {
    /* 省略无关代码... */

    function wrappedComponentStaic () {
      WrappedComponent.sayHello();
    }

    return (props: any) => (
      <div className={styles.hocWrapper}>
        <WrappedComponent
          inputRef={(el: any) => { inputElement = el; }}
          {...props}
        />
        /* 省略无关代码... */
        <input
          type="button"
          value="调用子组件static"
          onClick={wrappedComponentStaic}
          className={styles.callButton}
        />
      </div>
    );
}

export default HOC;
  • Эффект следующий:

Условный рендеринг через реквизит

  • Компоненты более высокого порядка, реализованные с помощью прокси свойств, не могут напрямую реализовать перехват рендеринга исходного компонента (т.renderконтроль не очень сильный), но может бытьpropsЧтобы контролировать, следует ли отображать и передавать данные:
import * as React from 'react';
import * as styles from './index.module.less';

function HOC (WrappedComponent: any) {
    /* 省略无关代码... */

    function wrappedComponentStaic () {
      WrappedComponent.sayHello();
    }

    return (props: any) => (
      <div className={styles.hocWrapper}>
        {
          props.isShow ? (
            <WrappedComponent
              {...props}
            />
          ) : <div>暂无数据</div>
        }
      </div>
    );
}

export default HOC;

Оберните входящий компонент другими элементами

  • Мы можем обернуть исходный компонент следующим образом, чтобы достичь цели макета или стиля:
function withBackgroundColor(WrappedComponent) {
    return class extends React.Component {
        render() {
            return (
                <div style={{ backgroundColor: '#ccc' }}>
                    <WrappedComponent {...this.props} {...newProps} />
                </div>
            );
        }
    };
}

обратное наследование

  • Обратное наследование относится к использованию функции для приема компонента в качестве параметра и возврата компонента класса, который наследует входящий компонент и возвращает компонент.render()возврат методаsuper.render()метод, простейшая реализация выглядит следующим образом:
const HOC = (WrappedComponent) => {
  return class extends WrappedComponent {
    render() {
      return super.render();
    }
  }
}
  • По сравнению с методом прокси-атрибутов компоненты высокого порядка, реализованные с помощью обратного наследования, характеризуются тем, что позволяют компонентам высокого порядка проходить черезthisДоступ к исходному компоненту, чтобы вы могли напрямую читать исходный компонент и работать с ним.state/ref/Методы жизненного цикла.
  • Компоненты более высокого порядка, реализованные с помощью обратного наследования, могут быть реализованы с помощьюsuper.render()Метод получает входящий экземпляр компонентаrenderВ результате перехват рендеринга может выполняться для входящих компонентов (самая большая функция), таких как:
    • Условно отображать дерево элементов (element tree)
    • управляетсяrender() выводReactдерево элементов
    • в любойrender()выводReactоперация в элементеprops
    • Оберните результат рендеринга входящего компонента другим элементом

Взлом исходного метода жизненного цикла компонента

  • Поскольку новый компонент, возвращаемый вышестоящим компонентом, реализованным обратным наследованием, наследуется от входящего компонента, когда новый компонент определяет тот же метод, он переопределяет метод экземпляра родительского класса (входящий компонент), как показано на показан следующий код:
function HOC(WrappedComponent){
  // 继承了传入组件
  return class HOC extends WrappedComponent {
    // 注意:这里将重写 componentDidMount 方法
    componentDidMount(){
      ...
    }

    render(){
      //使用 super 调用传入组件的 render 方法
      return super.render();
    }
  }
}
  • Хотя переопределения жизненного цикла переопределяются, мы можем перехватить жизненный цикл другими способами:
function HOC(WrappedComponent){
  const didMount = WrappedComponent.prototype.componentDidMount;
  
  // 继承了传入组件
  return class HOC extends WrappedComponent {
    componentDidMount(){
      // 劫持 WrappedComponent 组件的生命周期
      if (didMount) {
        didMount.apply(this);
      }
      ...
    }

    render(){
      //使用 super 调用传入组件的 render 方法
      return super.render();
    }
  }
}

Чтение/управление состоянием исходного компонента

  • Компоненты более высокого порядка, реализованные в обратном наследовании, могут читать, редактировать и удалять входящие экземпляры компонентов.state, как показано в следующем коде:
function HOC(WrappedComponent){
  const didMount = WrappedComponent.prototype.componentDidMount;
  // 继承了传入组件
  return class HOC extends WrappedComponent {
    async componentDidMount(){
      if (didMount) {
        await didMount.apply(this);
      }
      // 将 state 中的 number 值修改成 2
      this.setState({ number: 2 });
    }

    render(){
      //使用 super 调用传入组件的 render 方法
      return super.render();
    }
  }
}

рендеринг угона

условный рендеринг
  • Условный рендеринг означает, что мы можем решить, отображать ли компонент в соответствии с некоторыми параметрами (аналогично методу прокси свойства), например:
const HOC = (WrappedComponent) =>
  class extends WrappedComponent {
    render() {
      if (this.props.isRender) {
        return super.render();
      } else {
        return <div>暂无数据</div>;
      }
    }
  }
Изменить дерево элементов React
  • Мы также можем пройтиReact.cloneElementМетод измененrenderВывод дерева компонентов React методом:
// 例子来源于《深入React技术栈》
function HigherOrderComponent(WrappedComponent) {
  return class extends WrappedComponent {
    render() {
      const tree = super.render();
      const newProps = {};
      if (tree && tree.type === 'input') {
        newProps.value = 'something here';
      }
      const props = {
        ...tree.props,
        ...newProps,
      };
      const newTree = React.cloneElement(tree, props, tree.props.children);
      return newTree;
    }
  };
}

Сравнение прокси свойства и обратного наследования

  • В двух приведенных выше подразделах соответственно представлены компоненты более высокого порядка, реализованные с помощью прокси свойств и обратного наследования:

    • Атрибут прокси с точки зрения «комбинации», что способствует работе извне.WrappedComponent, объектами, которыми можно манипулировать, являютсяprops, или вWrappedComponentДобавьте несколько перехватчиков, контроллеров и т. д. снаружи.
    • Обратное наследование начинается с точки зрения «наследования» и действует изнутри.WrappedComponent, то есть вы можете манипулировать компонентами внутриstate,жизненный цикл,renderфункция и так далее.
  • Для удобства сравнения функции компонентов высшего порядка, реализованные двумя способами, перечислены следующим образом:

    список функций Риелтером обратное наследование
    Можно ли запаковать оригинальные компоненты?
    Наследуется ли исходный компонент ×
    Может читать/манипулировать исходным компонентомprops
    Может читать/манипулировать исходным компонентомstate
    может пройтиrefдоступ к оригинальному компонентуdomэлемент
    Влиять ли на какой-то жизненный цикл и другие методы исходного компонента
    Брать ли оригинальные комплектующиеstaticметод
    Можете ли вы перехватить исходный метод жизненного цикла компонента? ×
    Может отображать угон
  • Можно видеть, что компоненты более высокого порядка, реализованные с помощью метода обратного наследования, являются более мощными и более персонализированными, чем компоненты более высокого порядка, реализованные с помощью прокси атрибута, поэтому они могут адаптироваться к большему количеству сценариев.

Конкретная практика 💻

  • В этом разделе будут представлены некоторые практики использования компонентов более высокого порядка в бизнес-сценариях 🌰.

повторное использование страницы

  • Как упоминалось ранее, прокси свойств является наиболее распространенной реализацией компонентов более высокого порядка.Он по существу использует метод комбинирования для реализации функции повторного использования логики компонентов путем упаковки компонентов в компоненты-контейнеры. Поэтому, если вы хотите добиться повторного использования страницы, вы можете использовать компоненты более высокого порядка, реализованные с помощью прокси свойств.
  • Предположим, у нас естьpageAиpageBДва пользовательских интерфейса взаимодействуют с одной и той же страницей со списком фильмов, но, поскольку они относятся к разным категориям фильмов, источники данных и некоторый копирайтинг различаются, общее написание может быть таким:
// views/PageA.js
import React from 'react';
import fetchMovieListByType from '../lib/utils';
import MovieList from '../components/MovieList';

class PageA extends React.Component {
  state = {
    movieList: [],
  }
  /* ... */
  async componentDidMount() {
    const movieList = await fetchMovieListByType('comedy');
    this.setState({
      movieList,
    });
  }
  render() {
    return <MovieList data={this.state.movieList} emptyTips="暂无喜剧"/>
  }
}
export default PageA;

// views/PageB.js
import React from 'react';
import fetchMovieListByType from '../lib/utils';
import MovieList from '../components/MovieList';

class PageB extends React.Component {
  state = {
    movieList: [],
  }
  // ...
  async componentDidMount() {
    const movieList = await fetchMovieListByType('action');
    this.setState({
      movieList,
    });
  }
  render() {
    return <MovieList data={this.state.movieList} emptyTips="暂无动作片"/>
  }
}
export default PageB;
  • Путем наблюдения выясняется, что код двух страниц во многом совпадает, что на первый взгляд может показаться нормальным 🤦‍♀️. Однако с развитием бизнеса нужно запускать все больше и больше видов фильмов, и каждый раз при написании новой страницы будут добавляться какие-то повторяющиеся коды, что явно неразумно🙅, поэтому нужно повторять логику в на странице. Чтобы извлечь 🔬:
// HOC
import React from 'react';
const withFetchingHOC = (WrappedComponent, fetchingMethod, defaultProps) => {
  return class extends React.Component {
    async componentDidMount() {
      const data = await fetchingMethod();
      this.setState({
        data,
      });
    }
    
    render() {
      return (
        <WrappedComponent 
          data={this.state.data} 
          {...defaultProps} 
          {...this.props} 
        />
      );
    }
  }
}

// 使用:
// views/PageA.js
import React from 'react';
import withFetchingHOC from '../hoc/withFetchingHOC';
import fetchMovieListByType from '../lib/utils';
import MovieList from '../components/MovieList';
const defaultProps = {emptyTips: '暂无喜剧'}

export default withFetchingHOC(MovieList, fetchMovieListByType('comedy'), defaultProps);

// views/PageB.js
import React from 'react';
import withFetchingHOC from '../hoc/withFetchingHOC';
import fetchMovieListByType from '../lib/utils';
import MovieList from '../components/MovieList';
const defaultProps = {emptyTips: '暂无动作片'}

export default withFetchingHOC(MovieList, fetchMovieListByType('action'), defaultProps);;

// views/PageOthers.js
import React from 'react';
import withFetchingHOC from '../hoc/withFetchingHOC';
import fetchMovieListByType from '../lib/utils';
import MovieList from '../components/MovieList';
const defaultProps = {...}

export default withFetchingHOC(MovieList, fetchMovieListByType('some-other-type'), defaultProps);
  • Можно обнаружить, что компоненты высокого порядка, разработанные вышеwithFetchingHOC, извлекать измененные части (компоненты и методы получения данных) наружу в качестве входных данных, чтобы реализовать повторное использование страниц.

Контроль доступа

  • Предположим, есть такой сценарий: недавно будет запущена новая функция, которая включает в себя серию недавно разработанных страниц. Теперь необходимо добавить функцию белого списка на несколько из этих страниц, если пользователи, не входящие в белый список, посещают эти страницы, им будет предлагаться только копирайтинг, а соответствующие бизнес-данные отображаться не будут. Через неделю (приемка функции завершена) белый список будет удален, и он будет открыт для всех пользователей.
  • В приведенном выше сценарии есть несколько условий:
    • Многостраничная аутентификация: код аутентификации не может быть повторно записан в компоненте страницы;
    • Пользователи, не входящие в белый список, дают только подсказку о копирайтинге: перед запросом бизнес-данных в процессе аутентификации;
    • Удалите белый список через некоторое время: аутентификация должна быть полностью отделена от бизнеса, а добавление или удаление аутентификации должно свести к минимуму влияние на исходную логику.
  • Идеи: инкапсулировать процесс аутентификации, использовать характеристики условного рендеринга высокоуровневых компонентов, отображать соответствующие тексты в случае сбоя аутентификации и визуализировать бизнес-компоненты в случае успешной аутентификации. Поскольку и прокси свойства, и обратное наследование могут обеспечить условный рендеринг, мы будем использовать компонент более высокого порядка, реализованный относительно простым методом прокси свойства, для решения проблемы:
import React from 'react';
import { whiteListAuth } from '../lib/utils'; // 鉴权方法

/**
 * 白名单权限校验
 * @param WrappedComponent
 * @returns {AuthWrappedComponent}
 * @constructor
 */
function AuthWrapper(WrappedComponent) {
  return class AuthWrappedComponent extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        permissionDenied: -1,
      };
    }
    
    async componentDidMount() {
      try {
        await whiteListAuth(); // 请求鉴权接口
        this.setState({
          permissionDenied: 0,
        });
      } catch (err) {
        this.setState({
          permissionDenied: 1,
        });
      }
    }
    
    render() {
      if (this.state.permissionDenied === -1) {
        return null; // 鉴权接口请求未完成
      }
      if (this.state.permissionDenied) {
        return <div>功能即将上线,敬请期待~</div>;
      }
      return <WrappedComponent {...this.props} />;
    }
  }
}

export default AuthWrapper;
  • Для страниц, которые должны контролироваться разрешениями, вам нужно только передать компонент страницы в качестве параметра компоненту более высокого порядка.AuthWrapper✅.
  • Используя высокоуровневые компоненты, аутентификация и сервисы полностью отделены друг от друга, а при сбое аутентификации избегаются избыточные запросы служебных данных. оригинальный сервис Логика работы компонента также не нарушена ✌✌️✌️️.

Отслеживание производительности рендеринга компонентов

  • Оба описанных выше примера используют прокси атрибутов для реализации высокоуровневых компонентов.В представленном в этом разделе 🌰 используются высокоуровневые компоненты, реализованные с помощью обратного наследования, для отслеживания производительности рендеринга компонентов.
  • Как упоминалось ранее, ✍️, может ли компонент более высокого порядка, реализованный с помощью обратного наследования, перехватить метод жизненного цикла исходного компонента, поэтому, используя эту функцию, мы можем удобно записать время рендеринга компонента:
import React from 'react';
// Home 组件
class Home extends React.Component {
  render () {
    return (<h1>Hello World.</h1>);
  }
}

// HOC
function withTiming (WrappedComponent: any) {
  let start: number, end: number;

  return class extends WrappedComponent {
    constructor (props: any) {
      super(props);
      start = 0;
      end = 0;
    }
    componentWillMount () {
      if (super.componentWillMount) {
        super.componentWillMount();
      }
      start = +Date.now();
    }
    componentDidMount () {
      if (super.componentDidMount) {
        super.componentDidMount();
      }
      end = +Date.now();
      console.error(`${WrappedComponent.name} 组件渲染时间为 ${end - start} ms`);
    }
    render () {
      return super.render();
    }
  };
}

export default withTiming(Home);
  • результат:

Расширенное чтение (вопросы и ответы)

Заменят ли хуки компоненты более высокого порядка?

  • HookдаReact 16.8это новая функция, которая позволяет нам писатьclassиспользовать в случаеstateи другиеReactОсобенности (оHookСоответствующее введение можно прочитатьофициальная документация).
  • HookПоявление оригинала облегчает многие неловкие записи, наиболее типичным из которых является то, что он может заменитьclassДля большинства функций в жизненном цикле более связанная логика сгруппирована, а не разбросана по различным методам экземпляра жизненного цикла.
  • Несмотря на то чтоHookможет решить многие трудные задачи, но это, очевидно, не означает, чтоHookМогут заменить компоненты более высокого порядка, потому что у них все еще есть свои преимущества:
    • Компоненты более высокого порядка могут легко внедрять функциональность в базу через внешние протоколы.Component, поэтому его можно использовать как плагин, напримерreact-swipeable-viewsсерединаautoPlayКомпоненты более высокого порядка путем внедрения с сохранением состоянияpropsВместо написания кода непосредственно в основной библиотеке функция компонента расширена. заHookИными словами, его промежуточная обработка должна сильно зависеть от целевого компонента (неHookдефекты, толькоHookЯвно не предназначен для решения проблемы внедрения плагинов).
    • HookMore можно рассматривать как дополнение к решению с компонентами более высокого порядка, заполняющее ту часть, с которой компоненты более высокого порядка не справляются.HookМетод написания может сделать код более компактным и более подходящим для выполнения.ControllerИли нужна связная родственная логика.
    • В настоящее времяHookеще в начальной стадии(React 16.8.0только что официально выпущенHookстабильная версия), некоторые сторонние библиотеки на данный момент могут быть несовместимыHook.
  • Reactу чиновников нетclassотReactпредназначен для удаления вclassкомпоненты иHookмогут существовать одновременно. Чиновники также рекомендуют избегать любого «обширного рефакторинга», в конце концовHookэто очень новая функция, если она вам нравится, вы можете использовать ее в новом некритическом кодеHook.

Резюме 👀

  • Компонент более высокого порядка — это не компонент, это чистая функция, которая преобразует один компонент в другой.
  • Основная роль компонентов более высокого порядка заключается в повторном использовании кода и логической абстракции.stateиpropsВыполняйте абстракции и операции, уточняйте компоненты (например, добавляйте жизненные циклы), реализуйте перехват рендеринга и многое другое. Разумное использование компонентов высокого порядка в реальных бизнес-сценариях может повысить эффективность разработки и удобство сопровождения кода.
  • Полезность компонентов более высокого порядка 💪 делает их часто используемыми большим количествомReact.jsСвязанные сторонние библиотеки, такие какReact-Reduxизconnectметод,React-Loadableи т. д., используемые для понимания компонентов более высокого порядка для нашего понимания различныхReact.jsОбоснование сторонних библиотек полезно 👍.
  • Существует два способа реализации компонентов более высокого порядка, а именно прокси свойств и обратное наследование. Его можно рассматривать как шаблон декоратора вReactРеализация в: Улучшение функции компонента реализовано без изменения исходного компонента.
  • Некоторые специальные настройки обычно выполняются в проекте до разработки бизнес-кода, что полезно для последующей разработки проекта.Подробнее см. 👉:Процесс настройки проекта react + typescript.

Если есть какие-либо упущения или ошибки в вышеуказанном содержании, пожалуйста, оставьте сообщение ✍️Укажите и продвигайтесь вперед вместе💪💪💪

Если вы считаете, что эта статья полезна для вас, 🏀🏀 оставьте свой драгоценный 👍

использованная литература

  1. Компоненты высшего порядка (официальная документация)
  2. Разговор о компонентах высшего порядка React с тремя вопросами
  3. [Углубленное реагирование] От Mixin до HOC и Hook
  4. React Hooks для HoC и Render Props
  5. Вы действительно используете React Hooks, верно?
  6. Начало работы с ECMAScript 6 — Декораторы