React что такое компонент
Компоненты и пропсы
Компоненты позволяют разбить интерфейс на независимые части, про которые легко думать в отдельности. Их можно складывать вместе и использовать несколько раз. На этой странице мы ознакомимся с самой идеей компонентов — детальное описание API находится здесь.
Во многом компоненты ведут себя как обычные функции JavaScript. Они принимают произвольные входные данные (так называемые «пропсы») и возвращают React-элементы, описывающие, что мы хотим увидеть на экране.
Функциональные и классовые компоненты
Проще всего объявить React-компонент как функцию:
Эта функция — компонент, потому что она получает данные в одном объекте («пропсы») в качестве параметра и возвращает React-элемент. Мы будем называть такие компоненты «функциональными», так как они буквально являются функциями.
Ещё компоненты можно определять как классы ES6:
С точки зрения React, эти два компонента эквивалентны.
Функциональным и классовым компонентам доступны дополнительные возможности, о которых мы поговорим в следующих главах.
Как отрендерить компонент
Пока что мы только встречали React-элементы, представляющие собой DOM-теги:
Но элементы могут описывать и наши собственные компоненты:
Когда React встречает подобный элемент, он собирает все JSX-атрибуты и дочерние элементы в один объект и передаёт их нашему компоненту. Этот объект называется «пропсы» (props).
Например, этот компонент выведет «Привет, Алиса» на страницу:
Давайте разберём, что именно здесь происходит:
Привет, Алиса
Привет, Алиса
Примечание: Всегда называйте компоненты с заглавной буквы.
Если компонент начинается с маленькой буквы, React принимает его за DOM-тег. Например,
Чтобы узнать больше про это соглашение, прочитайте Углублённое изучение JSX.
Компоненты могут ссылаться на другие компоненты в возвращённом ими дереве. Это позволяет нам использовать одну и ту же абстракцию — компоненты — на любом уровне нашего приложения. Неважно, пишем ли мы кнопку, форму или целый экран: все они, как правило, представляют собой компоненты в React-приложениях.
Например, компонент App может отрендерить компонент Welcome несколько раз:
Не бойтесь разбивать компоненты на части.
Допустим, у нас есть компонент Comment :
Этот компонент представляет собой комментарий в социальной сети. Его пропсы включают в себя author (объект), text (строка), и date (дата).
С этим компонентом может быть не очень удобно работать из-за излишней вложенности. Мы также не можем повторно использовать его составные части. Давайте извлечём из него пару компонентов.
Для начала извлечём Avatar :
Пропсы следует называть так, чтобы они имели смысл в первую очередь с точки зрения самого компонента, а уже во вторую тех компонентов, которые его рендерят.
Теперь можно немножко упростить наш Comment :
Это позволит ещё сильнее упростить Comment :
Пропсы можно только читать
Компонент никогда не должен что-то записывать в свои пропсы — вне зависимости от того, функциональный он или классовый.
Возьмём для примера функцию sum :
Такие функции называют «чистыми», потому что они не меняют свои входные данные и предсказуемо возвращают один и тот же результат для одинаковых аргументов.
А вот пример нечистой функции — она записывает данные в свои же аргументы:
React достаточно гибкий, но есть одно правило, которое нельзя нарушать:
React-компоненты обязаны вести себя как чистые функции по отношению к своим пропсам.
Конечно, интерфейсы приложений обычно изменяются с течением времени. В следующей главе мы узнаем о том, что такое «состояние» компонента. Состояние даёт компонентам возможность реагировать на действия пользователя, ответы сервера и другие события, не нарушая чистоту компонента.
Компоненты и свойства
Компоненты позволяют разделить пользовательский интерфейс на независимые, повторно используемые части и работать с каждой из частей отдельно. На этой странице представлено введение в идею компонентов. Здесь вы можете найти подробный справочник API по компоненту.
Концептуально компоненты похожи на функции JavaScript. Они принимают произвольные входные данные (называемые «props» или свойствами) и возвращают React-элементы, описывающие, что должно появиться на экране.
Функциональные и классовые компоненты
Самый простой способ определить компонент — написать JavaScript-функцию:
Данная функция — корректный компонент React, потому что он принимает один аргумент-объект «props» (который обозначает свойства) с данными и возвращает элемент React. Такие компоненты мы называем «функциональными», потому что они являются буквально функциями JavaScript.
Вы также можете использовать класс из ES6 для определения компонента:
Два вышеуказанных компонента эквивалентны с точки зрения React.
У классов есть дополнительные возможности, которые мы обсудим в следующих разделах. До этого момента мы будем использовать функциональные компоненты из-за их краткости.
Раньше мы сталкивались только с элементами React, представляющие DOM-теги:
Однако элементы также могут быть пользовательскими компонентами:
Когда React видит элемент, представляющий пользовательский компонент, он передаёт JSX-атрибуты этому компоненту в виде единственного объекта. Мы называем этот объект «props».
Например, этот код отображает «Привет, Сара» на странице:
Давайте посмотрим, что происходит в этом примере:
Hello, Sara
Hello, Sara
Примечание: Всегда именуйте компоненты с заглавной буквы.
React обрабатывает компоненты, начинающиеся со строчных букв, как DOM-теги. Например,
Вы можете больше узнать о причинах, лежащих в основе этого соглашения здесь.
Компоненты могут ссылаться на другие компоненты в своём выводе. Это позволяет использовать одну и ту же абстракцию компонента для любого уровня детализации. Кнопка, форма, диалоговое окно, экран: в приложениях React все они обычно являются компонентами.
Не бойтесь разделять компоненты на более мелкие компоненты.
Например, рассмотрим этот компонент Comment :
Он принимает author (объект), text (строка) и date (дата) в качестве свойств и описывает комментарий на сайте социальных сетей.
Этот компонент может быть сложно изменить из-за вложенности, а также трудно повторно использовать отдельные его части. Давайте извлечём из него несколько компонентов.
Сначала мы извлечём Avatar :
Мы рекомендуем называть свойства объекта props с точки зрения самого компонента, а не контекста, в котором он используется.
Теперь мы можем чуть-чуть упростить Comment :
Это позволяет нам упростить Comment ещё больше:
Свойства объекта props доступны только для чтения
Независимо от того, объявляете ли компонент как функцию или класс, он не должен изменять свои свойства. Рассмотрим эту функцию sum :
Такие функции называются «чистыми», потому что они не пытаются изменить свои аргументы и всегда возвращают один и тот же результат для одних и тех же входных данных.
Напротив, функция ниже — не чистая, потому что она изменяет свои входные данные:
React довольно гибкий, но имеет одно строгое правило:
Все React-компоненты должны вести себя как чистые функции в плане своих свойств.
Конечно, пользовательские интерфейсы приложений динамичны и меняются со временем. В следующем разделе мы представим новую концепцию «состояние». Состояние позволяет компонентам React изменять свой вывод с течением времени в ответ на действия пользователя, сетевые ответы и что-либо ещё без нарушения правила выше.
React.Component
This page contains a detailed API reference for the React component class definition. It assumes you’re familiar with fundamental React concepts, such as Components and Props, as well as State and Lifecycle. If you’re not, read them first.
React lets you define components as classes or functions. Components defined as classes currently provide more features which are described in detail on this page. To define a React component class, you need to extend React.Component :
We strongly recommend against creating your own base component classes. In React components, code reuse is primarily achieved through composition rather than inheritance.
React doesn’t force you to use the ES6 class syntax. If you prefer to avoid it, you may use the create-react-class module or a similar custom abstraction instead. Take a look at Using React without ES6 to learn more.
The Component Lifecycle
Each component has several “lifecycle methods” that you can override to run code at particular times in the process. You can use this lifecycle diagram as a cheat sheet. In the list below, commonly used lifecycle methods are marked as bold. The rest of them exist for relatively rare use cases.
These methods are called in the following order when an instance of a component is being created and inserted into the DOM:
These methods are considered legacy and you should avoid them in new code:
An update can be caused by changes to props or state. These methods are called in the following order when a component is being re-rendered:
These methods are considered legacy and you should avoid them in new code:
This method is called when a component is being removed from the DOM:
These methods are called when there is an error during rendering, in a lifecycle method, or in the constructor of any child component.
Each component also provides some other APIs:
Commonly Used Lifecycle Methods
The methods in this section cover the vast majority of use cases you’ll encounter creating React components. For a visual reference, check out this lifecycle diagram.
The render() method is the only required method in a class component.
When called, it should examine this.props and this.state and return one of the following types:
The render() function should be pure, meaning that it does not modify component state, it returns the same result each time it’s invoked, and it does not directly interact with the browser.
If you need to interact with the browser, perform your work in componentDidMount() or the other lifecycle methods instead. Keeping render() pure makes components easier to think about.
render() will not be invoked if shouldComponentUpdate() returns false.
If you don’t initialize state and you don’t bind methods, you don’t need to implement a constructor for your React component.
The constructor for a React component is called before it is mounted. When implementing the constructor for a React.Component subclass, you should call super(props) before any other statement. Otherwise, this.props will be undefined in the constructor, which can lead to bugs.
Typically, in React constructors are only used for two purposes:
Constructor is the only place where you should assign this.state directly. In all other methods, you need to use this.setState() instead.
Avoid introducing any side-effects or subscriptions in the constructor. For those use cases, use componentDidMount() instead.
Avoid copying props into state! This is a common mistake:
The problem is that it’s both unnecessary (you can use this.props.color directly instead), and creates bugs (updates to the color prop won’t be reflected in the state).
Read our blog post on avoiding derived state to learn about what to do if you think you need some state to depend on the props.
componentDidMount() is invoked immediately after a component is mounted (inserted into the tree). Initialization that requires DOM nodes should go here. If you need to load data from a remote endpoint, this is a good place to instantiate the network request.
componentDidUpdate() is invoked immediately after updating occurs. This method is not called for the initial render.
Use this as an opportunity to operate on the DOM when the component has been updated. This is also a good place to do network requests as long as you compare the current props to previous props (e.g. a network request may not be necessary if the props have not changed).
You may call setState() immediately in componentDidUpdate() but note that it must be wrapped in a condition like in the example above, or you’ll cause an infinite loop. It would also cause an extra re-rendering which, while not visible to the user, can affect the component performance. If you’re trying to “mirror” some state to a prop coming from above, consider using the prop directly instead. Read more about why copying props into state causes bugs.
componentDidUpdate() will not be invoked if shouldComponentUpdate() returns false.
You should not call setState() in componentWillUnmount() because the component will never be re-rendered. Once a component instance is unmounted, it will never be mounted again.
Rarely Used Lifecycle Methods
The methods in this section correspond to uncommon use cases. They’re handy once in a while, but most of your components probably don’t need any of them. You can see most of the methods below on this lifecycle diagram if you click the “Show less common lifecycles” checkbox at the top of it.
Use shouldComponentUpdate() to let React know if a component’s output is not affected by the current change in state or props. The default behavior is to re-render on every state change, and in the vast majority of cases you should rely on the default behavior.
This method only exists as a performance optimization. Do not rely on it to “prevent” a rendering, as this can lead to bugs. Consider using the built-in PureComponent instead of writing shouldComponentUpdate() by hand. PureComponent performs a shallow comparison of props and state, and reduces the chance that you’ll skip a necessary update.
If you are confident you want to write it by hand, you may compare this.props with nextProps and this.state with nextState and return false to tell React the update can be skipped. Note that returning false does not prevent child components from re-rendering when their state changes.
getDerivedStateFromProps is invoked right before calling the render method, both on the initial mount and on subsequent updates. It should return an object to update the state, or null to update nothing.
This method exists for rare use cases where the state depends on changes in props over time. For example, it might be handy for implementing a
Deriving state leads to verbose code and makes your components difficult to think about. Make sure you’re familiar with simpler alternatives:
This method doesn’t have access to the component instance. If you’d like, you can reuse some code between getDerivedStateFromProps() and the other class methods by extracting pure functions of the component props and state outside the class definition.
This use case is not common, but it may occur in UIs like a chat thread that need to handle scroll position in a special way.
A snapshot value (or null ) should be returned.
In the above examples, it is important to read the scrollHeight property in getSnapshotBeforeUpdate because there may be delays between “render” phase lifecycles (like render ) and “commit” phase lifecycles (like getSnapshotBeforeUpdate and componentDidUpdate ).
Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed. Error boundaries catch errors during rendering, in lifecycle methods, and in constructors of the whole tree below them.
Only use error boundaries for recovering from unexpected exceptions; don’t try to use them for control flow.
Error boundaries only catch errors in the components below them in the tree. An error boundary can’t catch an error within itself.
This lifecycle is invoked after an error has been thrown by a descendant component. It receives the error that was thrown as a parameter and should return a value to update state.
getDerivedStateFromError() is called during the “render” phase, so side-effects are not permitted. For those use cases, use componentDidCatch() instead.
This lifecycle is invoked after an error has been thrown by a descendant component. It receives two parameters:
componentDidCatch() is called during the “commit” phase, so side-effects are permitted. It should be used for things like logging errors:
Production and development builds of React slightly differ in the way componentDidCatch() handles errors.
Legacy Lifecycle Methods
The lifecycle methods below are marked as “legacy”. They still work, but we don’t recommend using them in the new code. You can learn more about migrating away from legacy lifecycle methods in this blog post.
Avoid introducing any side-effects or subscriptions in this method. For those use cases, use componentDidMount() instead.
This is the only lifecycle method called on server rendering.
Using this lifecycle method often leads to bugs and inconsistencies
UNSAFE_componentWillReceiveProps() is invoked before a mounted component receives new props. If you need to update the state in response to prop changes (for example, to reset it), you may compare this.props and nextProps and perform state transitions using this.setState() in this method.
Note that if a parent component causes your component to re-render, this method will be called even if props have not changed. Make sure to compare the current and next values if you only want to handle changes.
UNSAFE_componentWillUpdate() is invoked just before rendering when new props or state are being received. Use this as an opportunity to perform preparation before an update occurs. This method is not called for the initial render.
Note that you cannot call this.setState() here; nor should you do anything else (e.g. dispatch a Redux action) that would trigger an update to a React component before UNSAFE_componentWillUpdate() returns.
UNSAFE_componentWillUpdate() will not be invoked if shouldComponentUpdate() returns false.
Unlike the lifecycle methods above (which React calls for you), the methods below are the methods you can call from your components.
setState() enqueues changes to the component state and tells React that this component and its children need to be re-rendered with the updated state. This is the primary method you use to update the user interface in response to event handlers and server responses.
Think of setState() as a request rather than an immediate command to update the component. For better perceived performance, React may delay it, and then update several components in a single pass. React does not guarantee that the state changes are applied immediately.
setState() does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState() a potential pitfall. Instead, use componentDidUpdate or a setState callback ( setState(updater, callback) ), either of which are guaranteed to fire after the update has been applied. If you need to set the state based on the previous state, read about the updater argument below.
The first argument is an updater function with the signature:
The second parameter to setState() is an optional callback function that will be executed once setState is completed and the component is re-rendered. Generally we recommend using componentDidUpdate() for such logic instead.
You may optionally pass an object as the first argument to setState() instead of a function:
This performs a shallow merge of stateChange into the new state, e.g., to adjust a shopping cart item quantity:
This form of setState() is also asynchronous, and multiple calls during the same cycle may be batched together. For example, if you attempt to increment an item quantity more than once in the same cycle, that will result in the equivalent of:
Subsequent calls will override values from previous calls in the same cycle, so the quantity will only be incremented once. If the next state depends on the current state, we recommend using the updater function form, instead:
For more detail, see:
defaultProps can be defined as a property on the component class itself, to set the default props for the class. This is used for undefined props, but not for null props. For example:
If props.color is not provided, it will be set by default to ‘blue’ :
The displayName string is used in debugging messages. Usually, you don’t need to set it explicitly because it’s inferred from the name of the function or class that defines the component. You might want to set it explicitly if you want to display a different name for debugging purposes or when you create a higher-order component, see Wrap the Display Name for Easy Debugging for details.
this.props contains the props that were defined by the caller of this component. See Components and Props for an introduction to props.
In particular, this.props.children is a special prop, typically defined by the child tags in the JSX expression rather than in the tag itself.
The state contains data specific to this component that may change over time. The state is user-defined, and it should be a plain JavaScript object.
If some value isn’t used for rendering or data flow (for example, a timer ID), you don’t have to put it in the state. Such values can be defined as fields on the component instance.
See State and Lifecycle for more information about the state.
2.5 Компоненты и свойства
Компоненты позволяют разделить UI на независимые, повторно используемые части и работать с каждой из них отдельно.
Концептуально, компоненты похожи на JavaScript-функции. Они принимают произвольные данные (называемые props) и возвращают React-элементы, которые описывают то, что должно появиться на экране.
2.5.1 Компоненты-функции и компоненты-классы
Самый простой способ объявить компонент – это написать JavaScript-функцию:
Эта функция является корректным React-компонентом, потому что она принимает единственный объект props с данными в качестве аргумента и возвращает React-элемент. Такие компоненты называются «функциональными», так как они и есть JavaScript-функции.
Компонент можно объявить другим способом. Для этого нужно использовать ES6-класс:
Два приведенных выше компонента являются эквивалентными с точки зрения React. Но пока мы будем использовать функциональные компоненты, так как они короче.
2.5.2 Отрисовка компонентов
Ранее, мы наталкивались лишь на React-элементы, которые представляли собой DOM-теги:
Тем не менее, элементы могут быть представлены пользовательскими(кастомными) компонентами:
Например, этот код отрисовывает на странице «Hello, Sara»:
Давайте прорезюмируем то, что произошло в этом примере:
Hello, Sara
Hello, Sara
Всегда именуйте свои компоненты с большой буквы.
Например,
2.5.3 Композиция компонентов
Компоненты могут ссылаться на другие компоненты в своём выводе (результате отрисовки). Это позволяет нам использовать ту же самую абстракцию компонента для любого уровня детализации. Кнопка, форма, диалог, экран: в React-приложении все эти сущности выражены компонентами.
Как правило, новые React-приложения имеют единственный компонент App на самом верху иерархии. Тем не менее, если вы интегрируете React в уже существующее приложение, вы можете начать снизу вверх с маленького компонента, такого как Button и постепенно двигаться вверх по иерархии отображения.
2.5.4 Извлечение компонентов
Не бойтесь разделять компоненты на более мелкие компоненты.
Рассмотрим пример с компонентом Comment :
Он принимает author (объект), text (строка) и date (дата) как свойства, и описывает комментарий на социальном веб-сайте.
Данный компонент довольно сложно изменить из-за его вложенности. Также тяжело повторно использовать и его составные части. Давайте извлечем из него несколько небольших компонентов, упростив исходный компонент.
Для начала давайте извлечем из него компонент Avatar :
Мы рекомендуем именовать props с точки зрения компонента, а не контекста, в котором он будет использован.
Сейчас мы можем немного упростить компонент Comment :
Это позволяет нам еще больше упростить компонент Comment :
Извлечение компонентов по началу может показаться рутинной работой. Однако набор универсальных, переиспользуемых, отлаженных компонентов с лихвой окупит все усилия в больших приложениях, экономя массу времени.
2.5.4 Свойства props – только для чтения
Такие функции называются «чистыми». Потому что они не изменяют свои аргументы и всегда возвращают одинаковый результат для одних и тех же аргументов.
В противоположность им, следующая функция не является чистой, потому что она изменяет свои аргументы:
React является очень гибким, но он имеет одно строгое правило:
Конечно, UI приложения – динамический и изменяется со временем. В следующем разделе мы познакомимся с новой концепцией «состояния». Состояние позволяет React-компонентам изменять их вывод со временем в ответ на действия пользователя, ответы сети или что-то другое, не нарушая данное правило.