Компоненты
Какие основные различия между компонентами классов и функциональными компонентами в React?
В React существуют два основных способа создания компонентов: с использованием классов и с использованием функциональных компонентов. Вот основные различия между ними:
Компоненты классов:-
Синтаксис: Компоненты классов определяются как классы, расширяющие базовый класс
React.Component. -
Состояние (state): Компоненты классов имеют встроенную поддержку для состояния (state), что позволяет им хранить и управлять данными внутри компонента.
-
Методы жизненного цикла: Компоненты классов обладают широким набором методов жизненного цикла (например,
componentDidMount,componentDidUpdate,componentWillUnmount), которые позволяют реагировать на различные этапы жизни компонента. -
Пропсы (props): Пропсы передаются в компоненты классов через атрибуты при использовании. Они доступны через
this.propsвнутри методов компонента.
-
Синтаксис: Функциональные компоненты определяются как обычные функции.
-
Состояние (state): Изначально функциональные компоненты не поддерживали состояние. Однако с появлением хуков (hooks) в React (начиная с React 16.8) функциональные компоненты теперь могут использовать состояние и другие возможности, которые ранее были доступны только компонентам классов.
-
Хуки (hooks): Функциональные компоненты могут использовать хуки, такие как
useState,useEffectи другие, для управления состоянием, эффектами и другими аспектами. -
Пропсы (props): Пропсы также передаются функциональным компонентам, но доступны они как аргументы функции.
В целом, с появлением хуков, функциональные компоненты стали предпочтительным выбором для большинства случаев в React, так как они обеспечивают более простой и читаемый синтаксис, а также упрощенный способ управления состоянием и эффектами.
Как реализовать PureComponent?
PureComponent используется для классовых компонентов. Для функциональных компонентов похожую оптимизацию по пропсам предоставляет memo, который не является хуком.
С использованием классов:import React, { PureComponent } from "react";
class MyPureComponent extends PureComponent {
render() {
return <div>{/* Ваш код компонента */}</div>;
}
}
export default MyPureComponent;
Для функционального компонента с memo:
import React, { memo } from "react";
const MyPureComponent = () => {
return <div>{/* Ваш код компонента */}</div>;
};
export default memo(MyPureComponent);
PureComponent поверхностно сравнивает новые и прежние props и state. memo по умолчанию сравнивает каждый проп через Object.is; собственное состояние и используемый контекст по-прежнему могут вызвать рендер. Это оптимизации, а не гарантия отсутствия повторного рендера.
Что такое HOC (Higher-Order Component) в React?
Высокоуровневый компонент (Higher-Order Component, HOC) - это паттерн в React, который позволяет повторно использовать логику компонентов, абстрагируя ее от самих компонентов. HOC не является частью API React, это скорее паттерн композиции компонентов.
HOC - это функция, которая принимает компонент и возвращает новый
компонент с дополнительной логикой. HOC позволяют вынести общие функциональные
или структурные аспекты компонентов и повторно использовать их с разными
компонентами.
Пример HOC:
import React from "react";
const withLogger = (WrappedComponent) => {
return class WithLogger extends React.Component {
componentDidMount() {
console.log("Компонент был отрисован");
}
render() {
return <WrappedComponent {...this.props} />;
}
};
};
const MyComponent = () => {
return <div>Содержимое компонента</div>;
};
const EnhancedComponent = withLogger(MyComponent);
export default EnhancedComponent;
В этом примере withLogger - это HOC, который добавляет логирование в метод componentDidMount. Затем компонент MyComponent обертывается HOC, создавая EnhancedComponent.
HOC позволяют:
-
Расширять функциональность компонентов без изменения самих компонентов.
-
Переиспользовать код и логику между разными компонентами.
-
Создавать общие паттерны для логирования, аутентификации, обработки ошибок и других аспектов.
Однако, с развитием React и появлением хуков, часть функциональности HOC теперь может быть реализована с использованием хуков, таких как useEffect, useContext и других. В большинстве случаев, использование хуков более предпочтительно.
В чем разница между HOC и компонентами рендер-пропсов (render props)?
Как HOC (Высокоуровневый компонент, Higher-Order Component), так и компоненты с рендер-пропсами представляют паттерны в React для повторного использования логики между компонентами. Однако, у них есть различия в том, как они реализованы и как они используются.
HOC
(Higher-Order Component):
-
HOC - это функция, которая принимает компонент и возвращает новый компонент с дополнительной логикой.
-
HOC можно использовать как обертку для компонентов, добавляя к ним общую функциональность.
-
HOC выполняются во время создания компонента, и логика, добавленная HOC, применяется при каждом рендере.
-
В HOC есть доступ к жизненным циклам компонента и его состоянию.
-
Пример HOC -
connectиз библиотеки Redux, который связывает компоненты с хранилищем состояния.
-
Компонент с рендер-пропсами - это компонент, который принимает функцию в качестве свойства и вызывает эту функцию для рендеринга чего-либо.
-
Компонент с рендер-пропсами позволяет передавать логику рендеринга непосредственно в компонент, который использует этот компонент с рендер-пропсами.
-
Логика рендеринга передается через функцию-пропс и может быть использована при необходимости.
-
Компонент с рендер-пропсами не имеет доступа к жизненным циклам родительского компонента, но может иметь доступ к состоянию через пропсы.
-
Пример компонента с рендер-пропсами - компоненты
MouseилиToggleв документации React.
Выбор между HOC и компонентами с рендер-пропсами зависит от конкретной ситуации и предпочтений разработчика. Оба паттерна позволяют достичь повторного использования логики, но с разными подходами.
Что такое фрагменты (fragments) в React?
Фрагменты (fragments) - это механизм в React, который позволяет вам группировать дочерние элементы без необходимости создавать лишние DOM-элементы. Они позволяют вернуть несколько элементов из компонента без оборачивания их в дополнительный DOM-контейнер.
До появления фрагментов, если вы хотели вернуть несколько элементов из компонента, вам приходилось обертывать их в дополнительный элемент (например, <div>) или использовать массив, что могло привести к лишнему уровню вложенности или проблемам с CSS.
С использованием фрагментов, это выглядит более чисто и эффективно:
import React from "react";
const MyComponent = () => {
return (
<>
<h1>Заголовок</h1>
<p>Параграф 1</p>
<p>Параграф 2</p>
</>
);
};
export default MyComponent;
Фрагменты могут быть объявлены с помощью пустых <> и </>, а внутри них вы можете размещать любое количество дочерних элементов.
Фрагменты особенно полезны, когда вам нужно вернуть несколько элементов из компонента, например, из условных блоков или маппинга массивов, и вы хотите избежать создания дополнительных контейнеров в DOM.
Как организовать переиспользование компонентов в React?
Переиспользование компонентов - один из основных принципов разработки в React. Это позволяет создавать эффективный и легко поддерживаемый код. Вот некоторые методы организации переиспользования компонентов:
-
Компоненты высшего порядка (HOC): Создание компонентов высшего порядка позволяет оборачивать другие компоненты, добавляя им определенное поведение. Это полезно для изоляции логики, которую вы хотите применить к нескольким компонентам.
-
Композиция компонентов: Строить более сложные компоненты путем комбинирования более простых. Компоненты, которые представляют более общие элементы (например, кнопки, карточки и т.д.), могут быть повторно использованы и настроены в зависимости от конкретных потребностей.
-
Render Props: Создание компонентов, которые передают функцию через свойство
childrenили другое определенное свойство. Это позволяет другим компонентам использовать эту функцию для внедрения своего контента. -
Хуки (Hooks): С React 16.8, хуки позволили переиспользовать состояние и логику в функциональных компонентах без использования классов. Вам даже можно создавать собственные пользовательские хуки для изоляции определенной функциональности.
-
Библиотеки компонентов: Существует множество библиотек компонентов, таких как Material-UI, Ant Design, Chakra UI и другие, предоставляющие готовые компоненты для переиспользования в ваших проектах.
-
Компоненты страниц (Page Components) и компоненты макета (Layout Components):
Разделение компонентов на те, которые отвечают за макет (навигация, боковая панель и т.д.) и те, которые отвечают за конкретное содержание страницы, может существенно повысить переиспользование.
-
Контейнеры и компоненты представления (Containers and Presentational Components):
Разделяйте компоненты на “умные” контейнеры, которые управляют состоянием и бизнес-логикой, и “глупые” компоненты представления, которые отображают данные, переданные им из контейнеров.
Следуя этим методам, вы сможете организовать эффективное переиспользование компонентов в вашем приложении, что упростит поддержку кода и ускорит разработку.
Что такое “управляемые компоненты” (controlled components)?
“Управляемые компоненты” (controlled components) - это понятие, связанное с управлением состоянием форм и ввода данных в React. В управляемых компонентах значение элемента ввода (например, текстового поля или чекбокса) контролируется состоянием React компонента, а не DOM элементом.
Когда компонент контролирует значение ввода, он хранит это значение в своем состоянии и обновляет его с помощью обработчиков событий (например, при изменении текста в поле ввода). Это позволяет иметь полный контроль над данными формы и легко реагировать на изменения.
Пример управляемого компонента с текстовым полем:
import React, { useState } from "react";
const ControlledComponent = () => {
const [inputValue, setInputValue] = useState("");
const handleInputChange = (event) => {
setInputValue(event.target.value);
};
return (
<div>
<input type="text" value={inputValue} onChange={handleInputChange} />
<p>Введенное значение: {inputValue}</p>
</div>
);
};
export default ControlledComponent;
В этом примере значение текстового поля inputValue связано со состоянием компонента. Когда значение текстового поля меняется, вызывается обработчик handleInputChange, который обновляет состояние и, следовательно, значение текстового поля.
Использование управляемых компонентов обеспечивает предсказуемость состояния, упрощает взаимодействие с данными и позволяет выполнять валидацию и другие операции над введенными данными перед их отправкой на сервер.
Что такое “неуправляемые компоненты” (uncontrolled components)?
“Неуправляемые компоненты” (uncontrolled components) - это понятие, противоположное управляемым компонентам, и оно относится к управлению состоянием форм и ввода данных в React. В случае неуправляемых компонентов, значение элемента ввода (например, input или textarea) хранится непосредственно в DOM, и React компонент не управляет этим значением.
Вместо использования состояния компонента для хранения значения элемента ввода, неуправляемые компоненты обращаются к DOM напрямую для получения и обновления значения.
Пример неуправляемого компонента с текстовым полем:
import React, { useRef } from "react";
const UncontrolledComponent = () => {
const inputRef = useRef(null);
const handleButtonClick = () => {
alert("Значение в поле ввода: " + inputRef.current.value);
};
return (
<div>
<input type="text" ref={inputRef} />
<button onClick={handleButtonClick}>Показать значение</button>
</div>
);
};
export default UncontrolledComponent;
В этом примере значение текстового поля не хранится в состоянии компонента. Вместо этого мы используем useRef для получения ссылки на DOM-элемент и затем получаем его значение через inputRef.current.value.
Неуправляемые компоненты могут быть полезны, когда у вас есть особые случаи или требования, где контроль над состоянием через React не является оптимальным подходом. Однако, в большинстве случаев, управляемые компоненты обеспечивают более предсказуемое и удобное управление данными в формах.