Pure component react что это
Простые советы по написанию чистого кода React-компонентов
Автор материала, перевод которого мы публикуем сегодня, делится советами, которые помогают делать чище код React-компонентов и создавать проекты, которые масштабируются лучше, чем прежде.
Избегайте использования оператора spread при передаче свойств
Начнём с анти-паттерна, с приёма работы, которым лучше не пользоваться в тех случаях, когда для этого нет конкретных, обоснованных причин. Речь идёт о том, что следует избегать использования оператора spread ( <. props>) при передаче свойств от родительских компонентов дочерним.
Передача свойств таким образом может, на самом деле, ускорить разработку. Но этот приём значительно усложняет обнаружение ошибок в коде. Разработчик начинает меньше доверять своим компонентам, это усложняет их рефакторинг, и, как результат, ошибки появляются в них раньше, чем в случаях, когда оператор spread для передачи свойств не используется.
Объявляйте функции, использующие несколько параметров, применяя объекты с параметрами
Если функция принимает несколько параметров — хорошо будет поместить их все в объект. Вот как это может выглядеть:
Если подходить к созданию сигнатур своих функций именно так — можно получить несколько заметных преимуществ перед обычным способом объявления функций:
При работе с обработчиками событий используйте функции, возвращающие функции-обработчики
Если вы знакомы с функциональным программированием — то знайте, что то, о чём я хочу сейчас рассказать, напоминает каррирование. Суть в том, что тут применяется заблаговременная установка некоторых параметров функции.
Взгляните на этот пример:
Как видите, такое оформление функции-обработчика событий помогает поддерживать дерево компонентов в чистоте.
Используйте объекты, хранящие пары ключ-значение вместо условного оператора
Если нужно выводить различные элементы, основываясь на некоей логике, я посоветовал бы пользоваться объектами, хранящими данные в формате ключ-значение (коллекциями записей), а не выражениями if/else.
Вот пример, в котором используется if/else:
А вот — пример использования объекта, хранящего соответствующие значения:
Использование этой простой стратегии делает компоненты более декларативными и упрощает понимание их кода. Это, кроме того, облегчает расширение функционала программы через добавление новых элементов в коллекцию записей.
Оформляйте в виде хуков компоненты, рассчитанные на многократное использование в проекте
Я считаю весьма полезным паттерн, о котором хочу рассказать в этом разделе.
Возможно, вы сталкивались или столкнётесь с ситуацией, когда окажется, что какие-то компоненты постоянно используются в разных частях приложения. Если им для работы нужно хранить что-то в состоянии приложения, это значит, что их можно обернуть в хуки, предоставляющие им это состояние. Удачными примерами подобных компонентов можно назвать всплывающие окна, тост-уведомления, простые модальные окна. Например — вот компонент, в котором, с использованием хука, реализовано простое модальное окно для подтверждения выполнения некоей операции:
Пользоваться этим хуком можно так:
Такой подход к абстрагированию компонентов избавляет программиста от необходимости написания больших объёмов шаблонного кода для управления состоянием приложения. Если вы хотите узнать о нескольких полезных хуках React — взгляните на этот мой материал.
Разделяйте код компонентов на части
Следующие три совета посвящены грамотному разделению компонентов на части. Опыт подсказывает мне, что лучший способ поддержания проекта в таком состоянии, чтобы проектом было бы удобно управлять, заключается в том, чтобы стремиться делать компоненты как можно компактнее.
▍Использование обёрток
Если вам сложно найти способ разбиения большого компонента на части — взгляните на функционал, предоставляемый каждым из его элементов. Некоторые элементы, например, существуют ради решения узкоспециализированных задач, например, для поддержки механизма drag-and-drop.
Вот пример компонента, реализующего drag-and-drop с использованием react-beautiful-dnd:
А теперь взгляните на тот же компонент после того, как мы переместили drag-and-drop-логику в компонент-обёртку:
В результате код компонента можно очень быстро прочесть и в общих чертах разобраться с тем, какую именно задачу решает этот компонент. А весь функционал, имеющий отношение к механизму drag-and-drop, размещён в компоненте-обёртке. С кодом, реализующим этот механизм, теперь тоже гораздо проще и удобнее работать.
▍Разделение обязанностей
Тут я хочу рассказать о моём любимом методе разделения больших компонентов на части.
В контексте React «разделение обязанностей» означает отделение тех частей компонента, которые ответственны за загрузку и преобразование данных, от тех частей, которые отвечают исключительно за отображения дерева элементов.
Паттерн «хук» появился именно благодаря идее разделения обязанностей. Можно и даже нужно оборачивать в хуки всю логику, ответственную за взаимодействие с некими API или с глобальным состоянием.
Например — давайте посмотрим на следующий компонент:
Ниже показано то, что получилось после его рефакторинга, в ходе которого его код разделён на части с применением пользовательских хуков. А именно — вот сам компонент:
▍Хранение кода каждого компонента в отдельном файле
Часто программисты пишут код компонентов примерно так:
И, хотя тут нет ничего ужасно неправильного, нельзя рекомендовать писать код именно так. У перемещения ItemDisplay в отдельный файл нет никаких минусов. При этом плюсом такого подхода можно назвать тот факт, что, после переноса кода компонента в отдельный файл, компоненты проекта оказываются слабее связаны друг с другом. Их, кроме того, легче будет расширять.
Итоги
Написание чистого кода, в основном, сводится к тому, чтобы внимательно и вдумчиво относиться к своему делу и находить время на изучение удачных и неудачных паттернов. Хорошие решения стоит включать в свои проекты, а анти-паттерны лучше обходить стороной. Собственно говоря, применение удачных паттернов помогает писать более чистый код React-компонентов. Паттерны, которыми я тут поделился, очень помогают мне в работе. Надеюсь, они пригодятся и вам.
Что вы посоветовали бы тем, кто хочет сделать код своих React-компонентов чище?
Pure Components
React components let us split the UI into independent, reusable pieces, and think about each piece in isolation. React components can be defined by extending from React.Component Class or React.PureComponent Class.
We have created different Component classes until now and all these classes were extending React.Component Class.
There are few use cases where we can use React Pure Components.
Lets look at one example.
We are developing one application in which we are displaying the Reports. Let the reports be Employee Reports or Stock Market Reports.
For this assume that we have created GetReports Component Class.
This Component Class gets the Reports by Calling a Web API and in the UI, we will have one Reload button using which user can reload the Reports so that he will get Updated Reports Data.
Now we have another Component which will be used to show if there are changes to the Reports Data. Lets say for every 5 seconds, this Component sends a request to the Web API and get the flag which tells whether there are any changes are not. If there are any changes, we will show a notification to the User, so that using Reload button user can get the updated Reports.
Lets open Index.js file from our demo-project
Lets create two Component Classes. One is DetectChanges Component Class and Other one is Reports Component Class. I have the Code handy and Pasting it here.
Save the Changes, Navigate to the Browser and we can see the Output.
We might feel that our code is working fine and we are getting the Results. But there are few issues with the code we have written here. Lets understand that.
For every 5 seconds, our changeDetection Component is sending a Web API request, getting the data and setting into the State Object.
Each time when we set the data into our state object or when we assign the property values, the component gets re-rendered.
We can see that for every 5 seconds we get that alert notification. That means our component is getting re-rendered though there is no change in the data. That is because our Component is not Pure.
In order to avoid re-rendering of our ChangeDetectionComponent when there are no changes to the state data, we will make ChangeDetection Component as Pure.
PureComponent is similar to Component. The difference between them is that Component doesn’t implement shouldComponentUpdate(), but PureComponent implements it with a shallow comparison of properties and state data.
PureComponent’s shouldComponentUpdate() method returns true or false If the previous state and props data is the same as the next props or state, resulting the component is not Re-rendered.
If our React component’s render() function renders the same result given the same props and state, we can use React.PureComponent for a performance boost.
Lets go to ChangeDetection Component Class, instead of extending it from react.Component Class, extend it from React.PureComponent Class. Save the Changes, navigate to the browser. We can observe that we will not get the alert Notification repeatedly.
That is because there is no change in the Employee Count so that Component has no need to re-render.
Lets go to our Web API and add a record to our list. Build this Project. Lets go to our React Application. Now we will get the Alert notification because the count value is changed.
Now we can click on the Reload button in the Reports Component to get the New Employee Record.
React Components re-renders in the following scenarios:
1. “setState” is called in Component
2. “props” values are updated
3. this.forceUpdate() is called
In the case of Pure Components, the React components do not re-render blindly without considering the updated values of React “props” and “state”. If updated values are the same as previous values, render is not triggered.
React.PureComponent’s shouldComponentUpdate() performs only shallow comparison of the data. If data is either of type Objects or complex data structures, it may result in wrong rendering behaviors.
Now the question is what is Shallow Comparison?
Shallow compare checks for equality. When comparing values of type number or string it compares their values.
When comparing objects, it checks whether both the objects are pointing to the Same location or not. The Property Values of the Objects are not Compared.
That means if we have two objects named emp and emp1, and if we shallow Compare them, then it returns false.
But if we assign emp to emp1 and do the Comparison, then it returns true.
Lets go to our ChangeDetection Component Class, to the state object, lets add one employee object.
In setInterval method, though we assign the same object to the employee property of the state object, still we get the Alert Notification. Its because of the Shallow Comparison. Because it looks for the object which is holding the address but not the same values.
Now lets assign the same state object employee property. Save these changes, navigate to the browser. We can see that we don’t get the Alert Notification recurrently.
Pure Components are introduced for performance enhancement. You can use this optimization to improve the performance of your components. But remember that it works well provided our state and props are Primitive types only but not reference types like object or Array.
Video Reference:
What is React Pure Component?
Let’s learn React pure component and how to implement one
Posted on November 25, 2020
By default, React will always re-render the component each time there is a change in state or props value. A Pure Component is a component that performs a check on the value of React props before deciding whether to re-render the component or not. Let me show you by an example.
Class-based PureComponent
Imagine you have an application that displays a movie title and release status:
Next, you have a MovieTitle component with the following content:
When you change the isReleased value by click on the button, you’ll find that MovieTitle gets re-rendered because React will print the log to the console. But actually, MovieTitle component doesn’t need to re-render because even if the value of isReleased is changed, its output remains the same.
To prevent the re-rendering and optimize your React app performance, you can extends the PureComponent class instead of Component :
Now when you click on toogle release, you won’t see React printing the log because MovieTitle will check the props and determine whether to render or not.
function-based PureComponent
The function will return a memoized component that you can call from other components:
Now you just need to call the memoized MovieTitle inside App component:
React’s “pure component” is a performance optimization method which implements the shouldComponentUpdate method underneath, but you should only use it sparingly, or even none at all.
This is because the performance optimization gained from using pure components are very trivial. React already re-render components very fast (as in less than 100 milliseconds fast, mostly around 20ms in small applications)
When you use pure components, comparing states and props will consume memory storage.
There will be a little delay because React has to compare the states and props before deciding whether to render or not. When React doesn’t re-render the component, you will gain a few milliseconds. When React does re-render, you will be slowed by a few milliseconds. Most people won’t be able to tell the difference anyway.
Level up your React skill today 🔥
Build FOUR projects using React with my latest book.
Structured knowledge from beginner to experienced level!
About
Nathan Sebhastian is a software engineer with a passion for writing tech tutorials. Learn JavaScript and other web development technology concepts through easy-to-understand explanations written in plain English.
React.Component
Эта страница содержит подробный справочник API для определения класса компонента React. Предполагается, что вы знакомы с фундаментальными концепциями React, такими как компоненты и свойства, а также состояние и жизненный цикл. Если вы этого не сделали, сначала прочитайте их.
React позволяет вам определять компоненты как классы или функции. В настоящее время компоненты, определённые как классы, предоставляют больше возможнотей, которые подробно описаны на этой странице. Чтобы определить класс компонента React, вам необходимо расширить React.Component :
Мы настоятельно не рекомендуем создавать собственные классы базовых компонентов. В React-компонентах повторное использование кода в основном достигается с помощью композиции, а не наследования.
React не заставляет вас использовать синтаксис класса ES6. Если вы предпочитаете избегать его использования, вы можете установить пакет create-react-class или аналогичную пользовательскую абстракцию. Посмотрите на Использование React без ES6, чтобы узнать больше.
Жизненный цикл компонента
Каждый компонент имеет несколько «методов жизненного цикла», которые вы можете переопределить для выполнения кода в определенное время в процессе. Вы можете использовать эту диаграмму жизненного цикла в качестве шпаргалки. В приведённом ниже списке обычно используемые методы жизненного цикла выделены полужирным шрифтом. Остальные из них существуют для относительно редких случаев использования.
Эти методы вызывают в следующем порядке, когда экземпляр компонента создаётся и добавляется в DOM:
Эти методы считаются устаревшими, и вам следует избегать их использование в новом коде:
Обновление может быть вызвано изменениями в свойствах или состоянии. Эти методы вызываются в следующем порядке, когда компонент повторно отрисовывается:
Эти методы считаются устаревшими, и вам следует избегать их использование в новом коде:
Этот метод вызывается, когда компонент удаляется из DOM:
Этот метод вызывается при возникновении ошибки во время отрисовки, в методе жизненного цикла или в конструкторе любого дочернего компонента.
Каждый компонент также предоставляет некоторые другие методы API:
Общеиспользуемые методы жизненного цикла
Методы в этом разделе охватывают подавляющее большинство случаев использования, с которыми вы столкнётесь при создании React-компонентов. Для наглядной иллюстрации ознакомьтесь с этой диаграммой жизненного цикла.
Метод render() — единственный обязательный методов в классовом компоненте.
При вызове он должен проверять this.props и this.state и возвращать один из следующих типов:
Функция render() должна быть чистой, что означает, что она не изменяет состояние компонента, она возвращает один и тот же результат при каждом вызове и не взаимодействует напрямую с браузером.
Если вам нужно взаимодействовать с браузером, выполняйте все необходимые операции в componentDidMount() или других методах жизненного цикла. Сохранение render() чистым делает компонент легче для понимания.
Если вы не инициализируете состояние и не привязываете методы, вам не нужно реализовывать конструктор в вашем React-компоненте.
Конструктор для компонента React вызывается до того, как будет примонтирован. При реализации конструктора подкласса React.Component вы должны называть super(props) перед любым другим выражением. В противном случае this.props не будет определен в конструкторе, что может привести к багам.
Как правило, в React конструкторы используются только для двух целей:
** Избегайте копирования свойств в состояние! Это распространённая ошибка:**
componentDidMount() вызывается сразу после монтирования компонента (вставлено в DOM-дерево). Инициализация, требующая DOM-узлов, должна быть здесь. Если вам нужно загружать данные с удалённой конечной точки (endpoint), это хорошее место для создания экземпляра сетевого запроса.
componentDidUpdate() вызывается сразу после обновления. Этот метод не вызывается при первоначальной отрисовке.
Используйте данный метод как возможность работать с DOM при обновлении компонента. Это также хорошее место для выполнения сетевых запросов, если вы сравниваете текущие свойства с предыдущими свойствами (например, не нужно делать сетевой запрос, если свойство не изменилось).
Редко используемые методы жизненного цикла
Методы в этом разделе соответствуют малораспространённым случаям использования. Они удобны время от времени, но большинство ваших компонентов, вероятно, не нуждаются ни в одном из них. Вы можете увидеть большинство приведенных ниже методов на этой диаграмме жизненного цикла, если наверху страницы вы нажмете на чекбокс «Show less common lifecycles».
Вывод состояния приводит к подробному коду и затрудняет понимание ваших компонентов. Убедитесь, что вы хорошо знакомы с более простыми альтернативами:
Если вы хотите повторно вычислить некоторые данные только при изменении свойств, используйте помощник мемоизации вместо этого.
Этот метод не имеет доступа к экземпляру компонента. Если вы хотите, то можете повторно использовать код между getDerivedStateFromProps() и другими методами класса, извлекая чистые функции свойства и состояния компонента вне определения класса.
Этот не распространённый вариант использования, но он может быть в пользовательских интерфейсах, таких как цепочка сообщений в чатах, который должен обрабатывать позицию прокрутки особым образом.
Должно быть возвращено значение снимка (или null ).
Граница ошибок — это React-компоненты, которые перехватывают ошибки JavaScript в любом месте их дочернего дерева компонентов, логируют эти ошибки и отображают резервный интерфейс вместо разрушенного дерева компонентов. Граница ошибок отлавливают ошибки при отрисовке, в методах жизненного цикла и в конструкторах всего дерева под ними.
Классовый компонент становится границей ошибки, если он определяет этот метод жизненного цикла. Вызов setState() в нём позволяет зафиксировать необработанную JavaScript-ошибку в приведённом ниже дереве и отобразить резервный интерфейс. Используйте только граница ошибок для восстановления от неожиданных исключений; не пытайтесь использовать их для управления потоком.
Для получения дополнительной информации смотрите раздел Обработка ошибок в React 16.
Граница ошибок перехватывают только ошибки в компонентах ниже в их дереве. Граница ошибки не может поймать ошибку внутри себя.
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.
Устаревшие методы жизненного цикла
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.
Это единственный хук жизненного цикла, вызываемый серверной отрисовкой.
Использование этого метода жизненного цикла часто приводит к ошибкам и несоответствиям.
UNSAFE_componentWillReceiveProps() вызывается до того, как смонтированный компонент получит новые свойства. Если вам нужно обновить состояние в ответ на изменения свойства (например, для его сброса), вы можете сравнить this.props и nextProps и выполнить переходы состояния с помощью this.setState() в этом методе.
Обратите внимание, что если родительский компонент заставляет ваш компонент повторно отрисовываться, этот метод будет вызываться, даже если свойства не изменились. Убедитесь в том, что сравниваете текущие и следующие значения, если вы только хотите обрабатывать изменения.
UNSAFE_componentWillUpdate() вызывается непосредственно перед отрисовкой при получении новых свойств или состояния. Используйте это как возможность выполнить подготовку до того, как произойдет обновление. Этот метод не вызывается при первоначальной отрисовке.
UNSAFE_componentWillUpdate() не будет вызываться, если shouldComponentUpdate() возвращает false.
В отличие от описанных выше методов жизненного цикла (которые React вызывает за вас), ниже приведены методы, которые вы можете вызывать из своих компонентов.
setState () ставит в очередь изменения в состояние компонента и указывает React, что этот компонент и его дочерние элементы должны быть повторно отрисованы с обновлённым состоянием. Это основной метод, который вы будете использовать для обновления пользовательского интерфейса в ответ на обработчики событий и ответы сервера.
Думайте о setState() как о запросе, а не как о команде немедленного действия для обновления компонента. Для лучшей очевидной производительности React может задержать выполнение, а затем обновить несколько компонентов за один проход. React не гарантирует незамедлительного применения изменений в состоянии.
Первый аргумент — это функция updater со следующим определением:
Второй параметр setState() — необязательный колбэк, вызываемый после завершения работы setState и далее компонент будет повторно отрисован. Обычно вместо этого мы рекомендуем использовать componentDidUpdate() для подобной логики.
Вы можете опционально передать объект в качестве первого аргумента setState() вместо функции:
Следующий фрагмент кода выполняет поверхностное объединение stateChange в новое состояние, например, чтобы скорректировать количество товаров в корзине:
Эта форма записи setState() также асинхронна, и несколько вызовов в течение одного цикла могут быть объединены (сгруппированы) вместе. Например, если вы пытаетесь увеличить количество элементов более одного раза в одном цикле, результат будет эквивалентным следующему ниже коду:
Последующие вызовы будут переопределять значения из предыдущих вызовов в том же самом цикле, поэтому количество будет увеличиваться только один раз. Если следующее состояние зависит от предыдущего состояния, мы рекомендуем использовать форму функции для обновления, т.е. следующим образом:
Для более подробной информации смотрите:
Если props.color не предоставлен, по умолчанию будет установлено значение ‘синий’ :
Строка displayName используется для отладочных сообщений. Обычно вам не нужно явно указывать её, поскольку по умолчанию предполагается имя функции или класса, который определяет компонент. Возможно, вы захотите установить его явно, если хотите отобразить другое имя для целей отладки или когда вы создаёте компонент высшего порядка, смотрите раздел Обтекание отображаемого имени для легкой отладки для получения подробной информации.
this.props содержит свойства, которые были определены вызывающим элементом этого компонента. Смотрите раздел Компоненты и реквизит для ознакомления со свойствами.
В частности, this.props.children — специальное свойство, обычно определяемое дочерними тегами в JSX-выражении, а не в самом теге.
Состояние содержит данные, конкретные для этого компонента, которые могут измениться со временем. Состояние определёно пользователем, и оно должно быть простым объектом JavaScript.
Если какое-либо значение не используется для отрисовки или потока данных (например, идентификатор таймера), вам не нужно вставлять его в состояние. Такие значения могут быть определены как поля экземпляра компонента.
Дополнительную информацию о состоянии смотрите в разделе Состояние и жизненный цикл.