React: различия между версиями

Материал из Home Wiki
Перейти к навигации Перейти к поиску
 
Строка 126: Строка 126:
     prevState[key] !== val && console.log(`State '${key}' changed`)
     prevState[key] !== val && console.log(`State '${key}' changed`)
   );
   );
}
</syntaxhighlight>
= Рендер динамического компонента с известными свойствами =
<syntaxhighlight>
interface IProps<P extends ICustomProps> {
  ...
  custom: new (props: P) => React.Component<P>;
}
class XXXX extends React.Component<IProps<ICustromProps>, IState> {
    public render() {
        ...
        const C = this.props.custom;
        component = (<C prop1={prop1} prop2={date} />);
        return (
            <div>
                {component}
            </div>
        );
    }
}
}
</syntaxhighlight>
</syntaxhighlight>

Текущая версия на 12:40, 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`)
  );
}

Рендер динамического компонента с известными свойствами

interface IProps<P extends ICustomProps> {
   ... 
  custom: new (props: P) => React.Component<P>;
}

class XXXX extends React.Component<IProps<ICustromProps>, IState> {
    public render() {
         ...
        const C = this.props.custom;
        component = (<C prop1={prop1} prop2={date} />);
        return (
            <div>
                {component}
            </div>
        );
    }
}