в документации говорится, что все компоненты React должны вести себя как чистые функции по отношению к своим реквизитам. https://facebook.github.io/react/docs/components-and-props.html, но не объясняет настоящую причину этого, почему так?
Почему компоненты ReactJS должны вести себя как чистые функции?
Ответы (4)
Компонент React должен быть чистым, это означает, что результат его метода render
должен зависеть исключительно от props
и state
, и для тех же свойств и состояния render
должен давать тот же результат.
Если рендеринг не является чистым, это означает, что он может возвращать разные результаты для одного и того же ввода, поэтому React не может сказать, какие части DOM необходимо обновить на основе изменений в компоненте. Это очень важно, так как от этого зависит производительность React. Почему? Это немного сложно.
Удивительно определять пользовательский интерфейс на основе состояния и перерисовывать пользовательский интерфейс каждый раз, когда изменяется какая-либо часть состояния. Но вы можете себе представить, что выполнение полного повторного рендеринга всего DOM каждый раз, когда вы что-то меняете, было бы мучительно медленным. React решает эту проблему, проверяя минимальное количество изменений, необходимых в DOM для отражения нового состояния. Он знает, что эти изменения основаны на том, какие свойства и состояние получает каждый компонент, и может сказать, нужно ли обновлять компонент, если какое-либо из его свойств или состояния изменилось.
Возьмите это дерево в качестве примера иерархии компонентов.
Здесь мы изменили h
на 8, поэтому мы также изменили f
, потому что h
является потомком f
, и мы также изменили c
, потому что f
является потомком c
и так далее.
Ключевым моментом здесь является то, как React проверяет дерево компонентов. Плохо начать с корня и увидеть, как он изменился. Затем он проверит всех дочерних элементов и обнаружит, что изменились только c
, поэтому нет необходимости проверять все ветки a
и b
. Затем он проверит ветвь c
и обнаружит, что изменена только f
, поэтому нет необходимости проверять e
и g
. Эта операция выполняется для каждого компонента, чтобы рассчитать минимальное количество изменений, а также то, что необходимо обновить.
Если в какой-то момент вы можете изменить способ рендеринга компонента, это означает, что React нужно будет проверить все ветки и все их дочерние элементы, чтобы узнать, что изменилось, потому что он не может полагаться на состояние и реквизиты, чтобы узнать, когда ветка изменилась. и как. Это было бы мучительно медленно и сделало бы весь фреймворк React нежизнеспособным.
Я бы сказал, из-за отслеживания изменений состояния компонента. Если он не чистый, он будет вызывать побочные эффекты при каждом выполнении. Таким образом, было бы очень трудно понять, что изменилось, и, кроме того, как реагировать на эти изменения.
Иными словами, чистые функции имеют одинаковый результат при одних и тех же входных данных. Это значительно упрощает управление свойствами и отслеживание изменений, что обеспечивает более простой и предсказуемый способ реагирования на изменения.
Если бы они не были чистыми функциями по отношению к своим реквизитам, тогда это нарушило бы всю структуру иерархии/делегирования, которую обеспечивает реакция и на которую она опирается.
Допустим, у вас есть два компонента, компонент A и компонент B, и компонент A является родительским для компонента B. Компонент A имеет свое собственное состояние, основанное на каких-то данных. Когда вы передаете часть своего состояния в качестве реквизита компоненту B, вы устанавливаете контракт между двумя компонентами, который компонент B делегирует компоненту A, чтобы получить значение указанного реквизита.
Это в некотором смысле контракт между двумя компонентами, и единственный способ не нарушить контракт — это то, что компонент B не изменяет напрямую или не изменяет переданную поддержку. Это то, что означает быть чистой функцией, что она не изменяет реквизит напрямую. Конечно, вы можете клонировать реквизит, а затем изменить его, как хотите, что не является нарушением контракта, поскольку в этот момент они не ссылаются на одни и те же значения. Но если вы измените свойства напрямую, вы также измените значение родительского компонента. Это может привести к непреднамеренным побочным эффектам, а также вызвать проблемы с алгоритмом разности теневых домов.
Вот что объясняется в официальной документации по реакции
Вы узнаете «почему», понимая алгоритм согласования, который React использует для рендеринга.
Здесь у вас есть вся информация, необходимая для понимания того, что вы хотите.
Частично это хорошо объяснено в ответе Марко Скаббиоло, но если вы хотите понять, как работает React, я настоятельно рекомендую вам прочитать пост, который я предложил.
Размещать ответ здесь было бы слишком много для поста и не нужно, потому что он уже объяснен командой React. Вот почему я предпочитаю давать вам источник напрямую.