React: различия между версиями
FireWolf (обсуждение | вклад) |
FireWolf (обсуждение | вклад) |
||
Строка 99: | Строка 99: | ||
* componentWillRecieveProps – UNSAFE_componentWillRecieveProps | * componentWillRecieveProps – UNSAFE_componentWillRecieveProps | ||
* componentWillUpdate – UNSAFE_componentWillUpdate | * componentWillUpdate – UNSAFE_componentWillUpdate | ||
= Controlled <-> uncontrolled input element = | |||
== Проявление == | |||
Ошибка возникающая в консоли в development-mode: | |||
<syntaxhighlight> | |||
Warning: A component is changing an uncontrolled input of type text to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). | |||
Decide between using a controlled or uncontrolled input element for the lifetime of the component. | |||
</syntaxhighlight> | |||
Означает, что компонент input был инициализирован в не контролируемом режиме и его переключили в контролируемый (или наоборот). | |||
Что же такое uncontrolled mode? Это инициализация input value={undefined}. | |||
Как исправить? input value={valueWithUndefinedState || ''} | |||
= Detect rerendering = | |||
https://stackoverflow.com/questions/41004631/trace-why-a-react-component-is-re-rendering | |||
<syntaxhighlight lang="typescript"> | |||
public componentDidUpdate(prevProps: any, prevState: any) { | |||
Object.entries(this.props).forEach(([key, val]) => | |||
prevProps[key] !== val && console.log(`Prop '${key}' changed`) | |||
); | |||
Object.entries(this.state).forEach(([key, val]) => | |||
prevState[key] !== val && console.log(`State '${key}' changed`) | |||
); | |||
} | |||
</syntaxhighlight> |
Версия 11:12, 6 июня 2019
Особенности
- В JSX в блоке return стоит оборачивать результат шаблона в ( <div>...</div> ); чтобы избежать проблем с обработчиками js кода, которые вставляют ; сами.
- Ключи помогают React идентифицировать, какой элемент был изменен, добавлен или удален для этого применяется атрибут key в компоненте.
- event.preventDefault(); - выполняет тоже самое, что и onclick="return false;"
Отладка
https://github.com/facebook/react-devtools
Состояние и жизненный цикл
Локальное состояние является возможностью, доступной только для классов. https://learn-reactjs.ru/basics/state-and-lifecycle
Метод componentDidMount() срабатывает после того, как компонент был отрисован в DOM.
Когда компонент в какой-то момент удалён из DOM, React вызывает метод componentWillUnmount() жизненного цикла.
https://m.habr.com/ru/post/358090/
Constructor
ДЕЛАЙТЕ:
- Устанавливайте изначальное состояние компонента
- Если не используется class properties синтаксис – подготовьте все поля класса и вызовете bind на тех функциях, что будут переданы как коллбеки.
НЕ ДЕЛАЙТЕ:
- Не выполняйте никаких сайд-эффектов (side effects) (Вызовы AJAX и т.д.)
[deprecated] componentWillMount
ДЕЛАЙТЕ:
- Обновляйте состояние через this.setState
- Выполняйте последние оптимизации
- Вызывайте сайд-эффекты (Вызов AJAX и т.д.) только в случае server-side-rendering.
НЕ ДЕЛАЙТЕ:
- Не выполняйте никаких сайд-эффектов (Вызов AJAX и т.д.) на стороне клиента.
[deprecated] componentWillReceiveProps(nextProps)
ДЕЛАЙТЕ:
- Синхронизируйте состояние (state) с props
НЕ ДЕЛАЙТЕ:
- Не выполняйте никаких сайд-эффектов (Вызовы AJAX и т.д.)
shouldComponentUpdate(nextProps, nextState, nextContext)
ДЕЛАЙТЕ:
- Используйте для оптимизации производительности компонента
НЕ ДЕЛАЙТЕ:
- Не выполняйте никаких сайд-эффектов (Вызовы AJAX и т.д.)
- Не вызывайте this.setState
[deprecated] componentWillUpdate(nextProps, nextState)
ДЕЛАЙТЕ:
- Синхронизируйте состояние (state) с props
НЕ ДЕЛАЙТЕ:
- Не выполняйте никаких сайд-эффектов (Вызовы AJAX и т.д.)
componentDidUpdate(prevProps, prevState, prevContext)
ДЕЛАЙТЕ:
- Выполняйте сайд-эффекты (Вызовы AJAX и т.д.)
НЕ ДЕЛАЙТЕ:
- Не вызывайте this.setState т.к. это будет вызывать циклическую перерисовку.
componentDidCatch(errorString, errorInfo)
С помощью этого дополнения вы можете сделать ваш родительский элемент обработчиком ошибок.
Когда происходит какая-либо ошибка, эта функция вызывается с следующими параметрами:
- errorString — .toString() сообщение о ошибке
- errorInfo – объект с одним полем componentStack, которое содержит стектрейс, где произошла ошибка.
componentDidMount
ДЕЛАЙТЕ:
- Выполняйте сайд-эффекты (Вызовы AJAX и т.д.)
НЕ ДЕЛАЙТЕ:
- Не вызывайте this.setState т.к. это вызовет перерисовку.
componentWillUnmount
ДЕЛАЙТЕ:
- Удаляйте таймеры и слушателей (listeners) созданных во время жизни компонента.
НЕ ДЕЛАЙТЕ:
- Не вызывайте this.setState, не стартуйте новых слушателей или таймеры.
React 16.3+ жизненный цикл компонента
static getDerivedStateFromProps(nextProps, prevState)
Основная ответственность этой новой функции — это убедиться, что состояние (state) и props синхронизированы, когда это необходимо. Ее основной смысл — это замена componentWillRecieveProps.
getSnapshotBeforeUpdate(prevProps, prevState)
Другая из двух новых функций, вызывается в так называемой “pre-commit фазе”, прямо перед изменениями из VDOM, которые должны быть отображены в DOM.
Устаревшие функции
Следующие функции будут маркированы как устаревшие и в следующих релизах переименованы:
- componentWillRecieveProps – UNSAFE_componentWillRecieveProps
- componentWillUpdate – UNSAFE_componentWillUpdate
Controlled <-> uncontrolled input element
Проявление
Ошибка возникающая в консоли в development-mode:
Warning: A component is changing an uncontrolled input of type text to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa).
Decide between using a controlled or uncontrolled input element for the lifetime of the component.
Означает, что компонент input был инициализирован в не контролируемом режиме и его переключили в контролируемый (или наоборот).
Что же такое uncontrolled mode? Это инициализация input value={undefined}.
Как исправить? input value={valueWithUndefinedState || }
Detect rerendering
https://stackoverflow.com/questions/41004631/trace-why-a-react-component-is-re-rendering
public componentDidUpdate(prevProps: any, prevState: any) {
Object.entries(this.props).forEach(([key, val]) =>
prevProps[key] !== val && console.log(`Prop '${key}' changed`)
);
Object.entries(this.state).forEach(([key, val]) =>
prevState[key] !== val && console.log(`State '${key}' changed`)
);
}