Что такое компонент высшего порядка в React?
Компонент высшего порядка — это функция, которая принимает компонент в качестве параметра и возвращает улучшенный или измененный компонент. Компонент высшего порядка (HOC) добавляет дополнительные данные или функциональность к исходному компоненту и возвращает его улучшенную версию.
HOC не изменяет исходный компонент. Он берет исходный компонент и оборачивает его в компонент-контейнер. Обернутый компонент получает данные и возвращает вывод в соответствии с полученными данными. HOC — это чистая функция.
Зачем использовать компонент высшего порядка?
-
HOC используется для разделения общих функциональных возможностей между компонентами
-
Помогает уменьшить дублирование кода
-
Делает код управляемым
Пример
Давайте создадим простое приложение React, которое будет подсчитывать количество нажатий на кнопку и наведение курсора на текст.
-
В вашем приложении React создайте папку с именем HOC. Внутри папки HOC мы создадим новый файл с именем ‘withCounter.js’. ‘withCounter.js’ — это компонент высшего порядка. ‘withCounter.js’ будет содержать логику, необходимую для построения системы счетчиков.
-
Теперь создайте еще одну папку с именем ‘components’. Внутри этой папки создайте компонент с именем ClickCounter.js.
import React from "react";
class ClickCounter extends React.Component {
render() {
return (
<div>
<button>Click me</button>
<p>Clicked X times</p>
</div>
);
}
}
export default ClickCounter;
- В той же папке создайте еще один компонент с именем HoverCounter.js.
import React from "react";
class HoverCounter extends React.Component {
render() {
return (
<div>
<h1>Hovered X times</h1>
</div>
);
}
}
export default HoverCounter;
Как вы видите, в обоих компонентах ClickCounter и HoverCounter мы должны создать состояние, которое будет увеличиваться на единицу каждый раз, когда мы нажимаем на кнопку или наводим курсор на текст. Итак, давайте напишем логику для реализации этой функциональности.
constructor(props) {
super(props)
this.state = {
count:0
}
}
incrementCount = () => {
this.setState(prevState => {
return {count: prevState.count + 1}
})
}
Здесь начальное состояние count установлено в ноль, а функция incrementCount будет увеличивать значение count на 1.
Теперь, один из способов заставить компоненты работать — это добавить приведенный выше фрагмент кода в оба компонента и запускать incrementCount при нажатии кнопки в ClickCounter и при наведении мыши в HoverCounter.
Другой способ — использовать компонент более высокого порядка, в который мы можем поместить count и incrementCount, а затем передать их в качестве реквизитов в ClickCounter и HoverCounter.
Для этого давайте откроем наш файл withCounter.js и напишем код.
import React from 'react'
const UpdatedComponent = (OriginalComponent) => {
class NewComponent extends React.Component{
constructor(props) {
super(props)
this.state = {
count:0
}
}
incrementCount = () => {
this.setState(prevState => {
return {count: prevState.count + 1}
})
}
render(){
return <OriginalComponent count={this.state.count} incrementCount={this.incrementCount } />
}
}
return NewComponent
}
export default UpdatedComponent
В этом HOC функция UpdatedComponent является стрелочной функцией, которая принимает OriginalComponent в качестве параметра. В нашем случае мы передадим ClickCounter и HoverCounter в качестве параметра OriginalComponent.
В этом HOC мы передаем count и incrementCount вниз в качестве реквизитов в OriginalComponent. Наконец, мы возвращаем NewComponent, который можно назвать улучшенной версией OriginalComponent.
- Теперь мы передадим ClickCounter и HoverCounter в качестве параметров в HOC withCounter.js. Итак, ClickCounter.js будет…
import React from "react";
import UpdatedComponent from "../HOC/withCounter";
class ClickCounter extends React.Component {
render() {
const { count, incrementCount } = this.props;
return (
<div>
<button onClick={incrementCount}>Click me</button>
<p>Hovered {count} times</p>
</div>
);
}
}
export default UpdatedComponent(ClickCounter);
- А HoverCounter.js будет выглядеть следующим образом
import React from 'react'
import UpdatedComponent from "../HOC/withCounter";
class HoverCounter extends React.Component {
render() {
const { count, incrementCount } = this.props;
return (
<div>
<h1 onMouseOver={incrementCount}>Hovered {count} times</h1>
</div>
);
}
};
export default UpdatedComponent(HoverCounter);
И конечный результат будет таким,
Теперь, в этом примере, мы также можем решить проблему, подняв состояние до общего родительского компонента. Но в более крупном приложении, если компоненты счетчиков ClickCounter.js и HoverCounter.js разбросаны, подъем состояния не будет правильным решением. В подобных случаях мы можем использовать компонент более высокого порядка.
Итак, вот как работает компонент высшего порядка.
Спасибо!!!