Как вы решите, как вы выбираете между этими тремя в зависимости от назначения / размера / реквизита / поведения наших компонентов?
Расширение из React.PureComponent
или React.Component
с помощью пользовательского shouldComponentUpdate
метода влияет на производительность. Использование функциональных компонентов без сохранения состояния является «архитектурным» выбором и не дает никаких преимуществ с точки зрения производительности (пока).
Для простых компонентов, предназначенных только для презентаций, которые необходимо легко использовать повторно, предпочитайте функциональные компоненты без сохранения состояния. Таким образом, вы уверены, что они не связаны с реальной логикой приложения, что их очень легко протестировать и у них нет неожиданных побочных эффектов. Исключение составляют случаи, когда по какой-то причине их много или вам действительно нужно оптимизировать их метод рендеринга (поскольку вы не можете определить shouldComponentUpdate
функциональный компонент без состояния).
Расширьте, PureComponent
если вы знаете, что ваш вывод зависит от простых реквизитов / состояния («простой», что означает отсутствие вложенных структур данных, так как PureComponent выполняет поверхностное сравнение) И вам нужно / можно получить некоторые улучшения производительности.
Расширьте Component
и внедрите свой собственный, shouldComponentUpdate
если вам нужно некоторое повышение производительности, выполняя пользовательскую логику сравнения между следующим / текущим реквизитом и состоянием. Например, вы можете быстро выполнить глубокое сравнение, используя lodash # isEqual:
class MyComponent extends Component {
shouldComponentUpdate (nextProps, nextState) {
return !_.isEqual(this.props, nextProps) || !_.isEqual(this.state, nextState);
}
}
Кроме того, реализация вашей собственной shouldComponentUpdate
или выход из нее PureComponent
является оптимизацией, и, как обычно, вы должны начать изучать ее, только если у вас есть проблемы с производительностью ( избегайте преждевременной оптимизации ). Как правило, я всегда стараюсь выполнять эти оптимизации после того, как приложение находится в рабочем состоянии, причем большинство функций уже реализовано. Намного легче сосредоточиться на проблемах производительности, когда они действительно мешают.
Подробнее
Функциональные компоненты без состояния:
Они определяются только с помощью функции. Поскольку для компонента без состояния не существует внутреннего состояния, вывод (то, что отображается) зависит только от реквизитов, заданных в качестве входных данных для этой функции.
Плюсы:
Простейший способ определения компонента в React. Если вам не нужно управлять каким-либо состоянием, зачем беспокоиться о классах и наследовании? Одно из основных различий между функцией и классом заключается в том, что с функцией вы уверены, что вывод зависит только от ввода (а не от истории предыдущих выполнений).
В идеале в вашем приложении вы должны стремиться иметь как можно больше компонентов без сохранения состояния, поскольку это обычно означает, что вы переместили свою логику за пределы слоя представления и переместили ее в нечто вроде избыточности, что означает, что вы можете проверить свою настоящую логику без необходимости что-либо визуализировать. (гораздо проще тестировать, больше использовать повторно и т. д.).
Минусы:
Нет методов жизненного цикла. У вас нет возможности определить componentDidMount
и других друзей. Обычно вы делаете это в родительском компоненте, находящемся выше в иерархии, чтобы вы могли превратить всех потомков в детей без состояния.
Нет способа вручную контролировать, когда требуется повторная визуализация, поскольку вы не можете определить shouldComponentUpdate
. Повторный рендеринг происходит каждый раз, когда компонент получает новые реквизиты (нет способа поверхностного сравнения и т. Д.). В будущем React может автоматически оптимизировать компоненты без сохранения состояния, а сейчас есть некоторые библиотеки, которые вы можете использовать. Поскольку компоненты без состояния - это просто функции, в основном это классическая проблема «запоминания функций».
Ссылки не поддерживаются: https://github.com/facebook/react/issues/4936
Компонент, который расширяет класс PureComponent VS Нормальный компонент, который расширяет класс Component:
React имел обыкновение иметь, PureRenderMixin
вы могли присоединиться к классу, определенному с использованием React.createClass
синтаксиса. Миксин будет просто определять shouldComponentUpdate
выполнение поверхностного сравнения между следующим реквизитом и следующим состоянием, чтобы проверить, изменилось ли что-нибудь там. Если ничего не меняется, то нет необходимости выполнять повторную визуализацию.
Если вы хотите использовать синтаксис ES6, вы не можете использовать миксины. Поэтому для удобства React представил PureComponent
класс, от которого вы можете наследовать, а не использовать Component
. PureComponent
просто реализует shouldComponentUpdate
таким же образом PureRendererMixin
. Это в основном удобство, поэтому вам не нужно реализовывать это самостоятельно, поскольку поверхностное сравнение между текущим / следующим состоянием и реквизитом, вероятно, является наиболее распространенным сценарием, который может дать вам быстрый выигрыш в производительности.
Пример:
class UserAvatar extends Component {
render() {
return <div><img src={this.props.imageUrl} /> {{ this.props.username }} </div>
}
}
Как видите, результат зависит от props.imageUrl
и props.username
. Если в родительском компоненте вы выполняете рендеринг <UserAvatar username="fabio" imageUrl="http://foo.com/fabio.jpg" />
с одинаковыми реквизитами, React будет вызывать render
каждый раз, даже если результат будет точно таким же. Однако помните, что React реализует dom diffing, поэтому DOM фактически не будет обновляться. Тем не менее, выполнение DOM Diffing может быть дорогостоящим, поэтому в этом случае это будет пустая трата времени.
Если UserAvatar
компонент расширяется PureComponent
, выполняется поверхностное сравнение. И потому, что реквизиты и nextProps одинаковы, render
не будет вызываться вообще.
Примечания к определению «чистый» в React:
В общем, «чистая функция» - это функция, которая всегда оценивает один и тот же результат при одинаковых входных данных. Вывод (для React, это то, что возвращается render
методом) не зависит от какой-либо истории / состояния и не имеет побочных эффектов (операций, которые изменяют «мир» вне функции).
В React компоненты без сохранения состояния не обязательно являются чистыми компонентами в соответствии с приведенным выше определением, если вы называете компонентом без состояния компонент, который никогда не вызывает this.setState
и не использует this.state
.
Фактически, PureComponent
вы все равно можете выполнять побочные эффекты во время методов жизненного цикла. Например, вы можете отправить ajax-запрос внутрь componentDidMount
или выполнить некоторое вычисление DOM, чтобы динамически настроить высоту div внутри render
.
Определение «тупых компонентов» имеет более «практическое» значение (по крайней мере, в моем понимании): тупому компоненту «говорят», что делать с родительским компонентом через реквизиты, и он не знает, как это делать, но использует реквизиты. обратные вызовы вместо.
Пример «умного» AvatarComponent
:
class AvatarComponent extends Component {
expandAvatar () {
this.setState({ loading: true });
sendAjaxRequest(...).then(() => {
this.setState({ loading: false });
});
}
render () {
<div onClick={this.expandAvatar}>
<img src={this.props.username} />
</div>
}
}
Пример "тупой" AvatarComponent
:
class AvatarComponent extends Component {
render () {
<div onClick={this.props.onExpandAvatar}>
{this.props.loading && <div className="spinner" />}
<img src={this.props.username} />
</div>
}
}
В конце я бы сказал, что «тупой», «не имеющий состояния» и «чистый» - это совершенно разные понятия, которые иногда могут перекрываться, но не обязательно, в зависимости, в основном, от вашего варианта использования.
props
. пример .PureComponent
не следует реализовыватьshouldComponentUpdate()
. Вы должны увидеть предупреждение, если вы делаете это на самом деле.PureComponent
компоненты, которые имеют вложенные свойства объекта / массива. Конечно, вы должны осознавать, что происходит. Если я правильно понимаю, если вы не изменяете реквизиты / состояние напрямую (что React пытается помешать вам делать с предупреждениями) или через внешнюю библиотеку, тогда вы должны нормально использоватьPureComponent
вместоComponent
почти везде ... за исключением очень простых компонентов, где на самом деле это может быть быстрее, НЕ использовать его - см. news.ycombinator.com/item?id=14418576я не гений, чтобы реагировать, но из моего понимания мы можем использовать каждый компонент в следующих ситуациях
Компонент без сохранения состояния - это компонент, у которого нет жизненного цикла, поэтому эти компоненты следует использовать при отображении элемента повторения родительского компонента, например при отображении текстового списка, который просто отображает информацию и не имеет каких-либо действий для выполнения.
Чистый компонент - это элементы, которые имеют жизненный цикл, и они всегда будут возвращать один и тот же результат, когда дается определенный набор реквизита. Эти компоненты могут использоваться при отображении списка результатов или данных конкретного объекта, которые не имеют сложных дочерних элементов и используются для выполнения операций, которые влияют только на себя. такое отображение списка пользовательских карточек или списка карточек продуктов (основная информация о товаре), и единственное действие, которое может выполнить пользователь, - это щелкнуть мышью, чтобы просмотреть подробную страницу или добавить в корзину.
Нормальные компоненты или сложные компоненты - я использовал термин сложный компонент, потому что они обычно являются компонентами уровня страницы и состоят из множества дочерних компонентов, и поскольку каждый из дочерних элементов может вести себя по-своему, поэтому вы не можете быть на 100% уверены, что он будет оказать тот же результат в данном состоянии. Как я уже сказал, обычно их следует использовать в качестве компонентов контейнера.
источник
PureComponent
компонентов корневого уровня и компонентов в верхней части иерархии, как правило, дает вам наибольшее повышение производительности. Конечно, вам нужно избегать мутирующих подпорок и указывать напрямую, чтобы чистые компоненты работали правильно, но мутирующие объекты напрямую в любом случае являются антишаблоном в React.React.Component
является стандартным компонентом по умолчанию. Вы объявляете их, используяclass
ключевое слово иextends React.Component
. Думайте о них как о классе, с методами жизненных циклов, обработчиками событий и другими методами.React.PureComponent
это то,React.Component
что реализуетshouldComponentUpdate()
с функцией, которая делает поверхностное сравнение егоprops
иstate
. Вы должны использовать,forceUpdate()
если вы знаете, что у компонента есть реквизиты или состояние вложенных данных, которые изменились, и вы хотите выполнить повторную визуализацию. Так что они не очень хороши, если вам нужны компоненты для повторного рендеринга, когда массивы или объекты, которые вы передаете как реквизиты или задаете в своем состоянии, меняются.Функциональные компоненты - это те, которые не имеют функций жизненного цикла. Они предположительно не имеют состояния, но они настолько хороши и чисты, что теперь у нас есть хуки (начиная с Реакта 16.8), так что у вас все еще может быть состояние. Так что я думаю, что они просто "чистые компоненты".
источник