React Компоненти класу
До React 16.8 компоненти класу були єдиним способом відстежувати стан і життєвий цикл компонента React. Функціональні компоненти вважалися "без стану".
З додаванням хуків компоненти Function тепер майже еквівалентні компонентам Class. Відмінності настільки незначні, що вам, мабуть, ніколи не знадобиться використовувати компонент Class у React.
Не дивлячись на те, що функціональні компоненти є кращими, наразі немає планів щодо видалення компонентів класу з React.
Цей розділ надасть вам огляд того, як використовувати компоненти класу в React.
Ви можете пропустити цей розділ і замість нього використовувати компоненти функції (Function).
Компоненти React
Компоненти — це незалежні фрагменти коду, які можна багаторазово використовувати. Вони служать тій самій меті, що й функції JavaScript, але працюють ізольовано та повертають HTML через функцію render().
Компоненти бувають двох типів: компоненти класу та компоненти функції. У цьому розділі ви дізнаєтесь про компоненти класу.
Створити компонент класу
Під час створення компонента React назва компонента має починатися з великої літери.
Компонент має включати інструкцію extends React.Component
, ця інструкція створює успадкування React.Component і надає вашому компоненту доступ до функцій React.Component.
Для компонента також потрібен метод render()
, цей метод повертає HTML.
Приклад
Створіть компонент Class під назвою Car
class Car extends React.Component {
render() {
return <h2>Hi, I am a Car!</h2>;
}
}
Тепер ваша програма React має компонент під назвою Car, який повертає елемент <h2>
.
Щоб використовувати цей компонент у своїй програмі, використовуйте синтаксис, подібний до звичайного HTML: <Car />
Приклад
Відобразити компонент Car
в "root" елементі:
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Car />);
Конструктор компонентів
Якщо у вашому компоненті є функція
, ця функція буде викликана, коли ініціюється компонент.constructor()
Функція конструктора – це місце, де ви ініціюєте властивості компонента.
У React властивості компонентів слід зберігати в об’єкті під назвою state
.
Ви дізнаєтеся більше про state
пізніше в цьому посібнику.
Функція конструктора — це також місце, де ви вшановуєте успадкування батьківського компонента, включаючи інструкцію super()
, яка виконує функцію конструктора батьківського компонента та ваш компонент має доступ до всіх функцій батьківського компонента (React.Component
).
Приклад
Створіть функцію-конструктор у компоненті Car і додайте властивість color:
class Car extends React.Component {
constructor() {
super();
this.state = {color: "red"};
}
render() {
return <h2>I am a Car!</h2>;
}
}
Використовуйте властивість color у функції render():
Приклад
class Car extends React.Component {
constructor() {
super();
this.state = {color: "red"};
}
render() {
return <h2>I am a {this.state.color} Car!</h2>;
}
}
Реквізит (props)
Іншим способом обробки властивостей компонента є використання props
.
Реквізити схожі на аргументи функції, і ви надсилаєте їх у компонент як атрибути.
Ви дізнаєтеся більше про props
в наступному розділі.
Приклад
Використовуйте атрибут, щоб передати колір компоненту Car, і використовуйте його у функції render():
class Car extends React.Component {
render() {
return <h2>I am a {this.props.color} Car!</h2>;
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Car color="red"/>);
Реквізити в конструкторі
Якщо ваш компонент має функцію конструктора, атрибути завжди слід передавати конструктору, а також React.Component через метод super()
.
Приклад
class Car extends React.Component {
constructor(props) {
super(props);
}
render() {
return <h2>I am a {this.props.model}!</h2>;
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Car model="Mustang"/>);
Компоненти в компонентах
Ми можемо посилатися на компоненти всередині інших компонентів:
Приклад
Використовуйте компонент Car всередині компонента Garage:
class Car extends React.Component {
render() {
return <h2>I am a Car!</h2>;
}
}
class Garage extends React.Component {
render() {
return (
<div>
<h1>Who lives in my Garage?</h1>
<Car />
</div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Garage />);
Компоненти у файлах
React — це повторне використання коду, і може бути доречним вставити деякі з ваших компонентів в окремі файли.
Для цього створіть новий файл із розширенням .js
і вставте в нього код:
Зверніть увагу, що файл має починатися з імпортування React (як і раніше), і він має закінчуватися інструкцією export default Car;
.
Приклад
Це новий файл, ми його назвали Car.js
:
import React from 'react';
class Car extends React.Component {
render() {
return <h2>Hi, I am a Car!</h2>;
}
}
export default Car;
Щоб мати можливість використовувати компонент Car
, потрібно імпортувати файл у свою програму.
Приклад
Тепер ми імпортуємо файл Car.js
у додаток і можемо використовувати компонент Car
так, ніби його було створено тут.
import React from 'react';
import ReactDOM from 'react-dom/client';
import Car from './Car.js';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Car />);
Стан (state) компонента класу React
Компоненти класу React мають вбудований об’єкт state
.
Ви могли помітити, що раніше ми використовували state
у розділі конструктора компонентів.
Об’єкт state
– це місце, де ви зберігаєте значення властивостей, які належать компоненту.
Коли об’єкт state
змінюється, компонент повторно відображається.
Створення об’єкта стану (state)
Об’єкт state ініціалізується в конструкторі:
Приклад
Укажіть об’єкт state
у методі конструктора:
class Car extends React.Component {
constructor(props) {
super(props);
this.state = {brand: "Ford"};
}
render() {
return (
<div>
<h1>My Car</h1>
</div>
);
}
}
Об’єкт стану (state) може містити скільки завгодно властивостей:
Приклад
Укажіть усі властивості, необхідні вашому компоненту:
class Car extends React.Component {
constructor(props) {
super(props);
this.state = {
brand: "Ford",
model: "Mustang",
color: "red",
year: 1964
};
}
render() {
return (
<div>
<h1>My Car</h1>
</div>
);
}
}
Використання об’єкта state
Зверніться до об’єкта state
будь-де в компоненті за допомогою синтаксиса this.state.назва_властивості
:
Приклад:
Зверніться до об’єкта state
у методі render()
:
class Car extends React.Component {
constructor(props) {
super(props);
this.state = {
brand: "Ford",
model: "Mustang",
color: "red",
year: 1964
};
}
render() {
return (
<div>
<h1>My {this.state.brand}</h1>
<p>
It is a {this.state.color}
{this.state.model}
from {this.state.year}.
</p>
</div>
);
}
}
Зміна об’єкта state
Щоб змінити значення в об’єкті state, скористайтеся методом this.setState()
.
Коли значення в об’єкті state
змінюється, компонент повторно відтворюється, тобто вихідні дані змінюватимуться відповідно до нових значень.
Приклад:
Додайте кнопку з подією onClick
, яка змінить властивість кольору:
class Car extends React.Component {
constructor(props) {
super(props);
this.state = {
brand: "Ford",
model: "Mustang",
color: "red",
year: 1964
};
}
changeColor = () => {
this.setState({color: "blue"});
}
render() {
return (
<div>
<h1>My {this.state.brand}</h1>
<p>
It is a {this.state.color}
{this.state.model}
from {this.state.year}.
</p>
<button
type="button"
onClick={this.changeColor}
>Change color</button>
</div>
);
}
}
Завжди використовуйте метод setState()
, щоб змінити об’єкт state, це гарантує, що компонент дізнається, що його оновлено, і викликає метод render() (і всі інші методи життєвого циклу).
Життєвий цикл компонентів
Кожен компонент у React має життєвий цикл, який ви можете контролювати та керувати ним протягом трьох основних фаз.
Це три етапи: Монтування, Оновлення та Демонтування.
Монтування (встановлення)
Монтування (встановлення) означає розміщення елементів у DOM.
React має чотири вбудовані методи, які викликаються в такому порядку під час монтування компонента:
constructor()
getDerivedStateFromProps()
render()
componentDidMount()
Метод render()
є обов’язковим і завжди викликатиметься, інші є необов’язковими та викликатимуться, якщо ви їх визначите.
constructor
Метод constructor()
викликається перед будь-чим іншим, коли компонент ініціюється, і це природне місце для налаштування початкового state
та інші початкові значення.
Метод constructor()
викликається з props
як аргументами, і вам слід завжди починати шляхом виклику super(props)
перед будь-чим іншим, це ініціює метод конструктора батьківського компонента та дозволить компоненту успадкувати методи від свого батьківського (React.Component
).
Приклад:
Метод constructor
викликається React щоразу, коли ви створюєте компонент:
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {favoritecolor: "red"};
}
render() {
return (
<h1>My Favorite Color is {this.state.favoritecolor}</h1>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header />);
getDerivedStateFromProps
Метод getDerivedStateFromProps()
викликається безпосередньо перед відтворенням елемента(ів) у DOM.
Це природне місце для встановлення об’єкта state
на основі початкових props
(реквізитів).
Він приймає state
як аргумент і повертає об’єкт зі змінами state
.
Наведений нижче приклад починається з "red", але метод getDerivedStateFromProps()
оновлює улюблений колір на основі атрибуту favcol
:
Приклад:
Метод getDerivedStateFromProps
викликається безпосередньо перед методом рендерингу:
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {favoritecolor: "red"};
}
static getDerivedStateFromProps(props, state) {
return {favoritecolor: props.favcol };
}
render() {
return (
<h1>My Favorite Color is {this.state.favoritecolor}</h1>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header favcol="yellow"/>);
render
Метод render()
є обов’язковим, і це метод, який фактично виводить HTML у DOM.
Приклад:
Простий компонент із простим методом render()
:
class Header extends React.Component {
render() {
return (
<h1>This is the content of the Header component</h1>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header />);
componentDidMount
Метод componentDidMount()
викликається після відтворення компонента.
Тут ви запускаєте інструкції, які вимагають, щоб компонент уже було розміщено в DOM.
Приклад:
Спочатку мій улюблений колір червоний (red), але дайте мені інший, і замість нього він жовтий (yellow):
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {favoritecolor: "red"};
}
componentDidMount() {
setTimeout(() => {
this.setState({favoritecolor: "yellow"})
}, 1000)
}
render() {
return (
<h1>My Favorite Color is {this.state.favoritecolor}</h1>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header />);
Оновлення
Наступною фазою життєвого циклу є оновлення компонента.
Компонент оновлюється щоразу, коли в компоненті вносяться зміни state
або props
.
React має п’ять вбудованих методів, які викликаються в такому порядку під час оновлення компонента:
getDerivedStateFromProps()
shouldComponentUpdate()
render()
getSnapshotBeforeUpdate()
componentDidUpdate()
Метод render()
є обов’язковим і завжди викликатиметься, інші є необов’язковими та викликатимуться, якщо ви їх визначите.
getDerivedStateFromProps
Також під час оновлень викликається метод getDerivedStateFromProps
. Це перший метод, який викликається, коли компонент оновлюється.
Це все ще є природним місцем для встановлення об’єкта state
на основі початкових параметрів.
Наведений нижче приклад містить кнопку, яка змінює улюблений колір на синій, але оскільки викликається метод getDerivedStateFromProps()
, який оновлює стан color за допомогою атрибуту favcol, улюблений колір все ще відображається як жовтий:
Приклад:
Якщо компонент оновлюється, викликається метод getDerivedStateFromProps()
:
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {favoritecolor: "red"};
}
static getDerivedStateFromProps(props, state) {
return {favoritecolor: props.favcol };
}
changeColor = () => {
this.setState({favoritecolor: "blue"});
}
render() {
return (
<div>
<h1>My Favorite Color is {this.state.favoritecolor}</h1>
<button type="button" onClick={this.changeColor}>Change color</button>
</div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header favcol="yellow" />);
shouldComponentUpdate
У методі shouldComponentUpdate()
ви можете повернути логічне значення, яке вказує, чи повинен React продовжувати рендеринг чи ні.
Значення за умовчанням — true
.
Наведений нижче приклад показує, що відбувається, коли метод shouldComponentUpdate()
повертає false
:
Приклад:
Зупиніть відтворення компонента під час будь-якого оновлення:
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {favoritecolor: "red"};
}
shouldComponentUpdate() {
return false;
}
changeColor = () => {
this.setState({favoritecolor: "blue"});
}
render() {
return (
<div>
<h1>My Favorite Color is {this.state.favoritecolor}</h1>
<button type="button" onClick={this.changeColor}>Change color</button>
</div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header />);
Приклад:
Той самий приклад, що й вище, але цього разу метод shouldComponentUpdate()
замість цього повертає true
:
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {favoritecolor: "red"};
}
shouldComponentUpdate() {
return true;
}
changeColor = () => {
this.setState({favoritecolor: "blue"});
}
render() {
return (
<div>
<h1>My Favorite Color is {this.state.favoritecolor}</h1>
<button type="button" onClick={this.changeColor}>Change color</button>
</div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header />);
render
Метод render()
, звичайно, викликається, коли компонент оновлюється, він має повторно відобразити HTML у DOM, за допомогою нових змін.
У прикладі нижче є кнопка, яка змінює улюблений колір на синій:
Приклад:
Натисніть кнопку, щоб змінити стан компонента:
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {favoritecolor: "red"};
}
changeColor = () => {
this.setState({favoritecolor: "blue"});
}
render() {
return (
<div>
<h1>My Favorite Color is {this.state.favoritecolor}</h1>
<button type="button" onClick={this.changeColor}>Change color</button>
</div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header />);
getSnapshotBeforeUpdate
У методі getSnapshotBeforeUpdate()
ви маєте доступ до props
і state
до оновлення, тобто навіть після оновлення ви можете перевірити, які значення були до оновлення.
Якщо метод getSnapshotBeforeUpdate()
присутній, ви також повинні включити метод componentDidUpdate()
, інакше ви отримаєте помилку.
Наведений нижче приклад може здатися складним, але все, що він робить, це:
Коли компонент монтується, він відображається улюбленим кольором "red".
Коли компонент встановлено, таймер змінює стан, і через одну секунду улюблений колір стає "yellow".
Ця дія запускає фазу оновлення, і оскільки цей компонент має метод getSnapshotBeforeUpdate()
, цей метод виконується та записує повідомлення до порожнього елемента DIV1.
Потім виконується метод componentDidUpdate()
і записує повідомлення в порожній елемент DIV2:
Приклад:
Використовуйте метод getSnapshotBeforeUpdate()
, щоб дізнатися, як виглядав об’єкт state
до оновлення:
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {favoritecolor: "red"};
}
componentDidMount() {
setTimeout(() => {
this.setState({favoritecolor: "yellow"})
}, 1000)
}
getSnapshotBeforeUpdate(prevProps, prevState) {
document.getElementById("div1").innerHTML =
"До оновлення фаворит був " + prevState.favoritecolor;
}
componentDidUpdate() {
document.getElementById("div2").innerHTML =
"Оновлений фаворит є " + this.state.favoritecolor;
}
render() {
return (
<div>
<h1>Мій улюблений колір {this.state.favoritecolor}</h1>
<div id="div1"></div>
<div id="div2"></div>
</div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header />);
componentDidUpdate
Метод componentDidUpdate
викликається після оновлення компонента в DOM.
Наведений нижче приклад може здатися складним, але все, що він робить, це:
Коли компонент монтується, він відображається улюбленим кольором "red".
Коли компонент змонтовано, таймер змінює стан, і колір стає "yellow".
Ця дія запускає фазу оновлення, і оскільки цей компонент має метод componentDidUpdate
, цей метод виконується та записує повідомлення в порожній елемент DIV:
Приклад:
Метод componentDidUpdate
викликається після відтворення оновлення в DOM:
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {favoritecolor: "red"};
}
componentDidMount() {
setTimeout(() => {
this.setState({favoritecolor: "yellow"})
}, 1000)
}
componentDidUpdate() {
document.getElementById("mydiv").innerHTML =
"The updated favorite is " + this.state.favoritecolor;
}
render() {
return (
<div>
<h1>My Favorite Color is {this.state.favoritecolor}</h1>
<div id="mydiv"></div>
</div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header />);
Демонтування
Наступною фазою життєвого циклу є видалення компонента з DOM або демонтування, як це любить називати React.
React має лише один вбудований метод, який викликається, коли компонент демонтовано:
componentWillUnmount()
componentWillUnmount
Метод componentWillUnmount
викликається, коли компонент необхідно видалити з DOM.
Приклад:
Натисніть кнопку, щоб видалити заголовок:
class Container extends React.Component {
constructor(props) {
super(props);
this.state = {show: true};
}
delHeader = () => {
this.setState({show: false});
}
render() {
let myheader;
if (this.state.show) {
myheader = <Child />;
};
return (
<div>
{myheader}
<button type="button" onClick={this.delHeader}>Delete Header</button>
</div>
);
}
}
class Child extends React.Component {
componentWillUnmount() {
alert("Компонент під назвою Header збирається демонтуватись.");
}
render() {
return (
<h1>Hello World!</h1>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Container />);