Почему не работает this.props.children.map?

this.props.children не является массивом; это непрозрачная структура данных, представляющая компоненты, переданные в качестве дочерних элементов компоненту React. В результате вы не можете напрямую использовать методы массива, такие как map(), для this.props.children.

Чтобы работать с this.props.children, вам нужно преобразовать его в массив, прежде чем использовать методы массива. Вы можете использовать утилиту React.Children для преобразования this.props.children в массив, а затем применить к нему map().

Пример:

import React from 'react';

class ParentComponent extends React.Component {
  render() {
    // Convert this.props.children to an array and then use map
    const childrenArray = React.Children.toArray(this.props.children);

    // Now you can use map on childrenArray
    const modifiedChildren = childrenArray.map((child, index) => {
      // Process or modify each child component here
      return child;
    });

    return <div>{modifiedChildren}</div>;
  }
}

// Usage of ParentComponent
const App = () => {
  return (
    <ParentComponent>
      <ChildComponent />
      <AnotherChildComponent />
    </ParentComponent>
  );
};

Можете ли вы заставить компонент React выполнить повторную визуализацию без вызова setState?

Да, вы можете заставить компонент React выполнить повторную визуализацию без вызова setState(), используя метод forceUpdate(). Однако важно отметить, что использование forceUpdate() в большинстве случаев не рекомендуется, и вы должны предпочесть использовать setState() для запуска обновлений компонентов, когда это возможно.

Пример:

import React from 'react';

class MyComponent extends React.Component {
  handleButtonClick = () => {
    // Call forceUpdate() to trigger a re-render
    this.forceUpdate();
  };

  render() {
    return (
      <div>
        <button onClick={this.handleButtonClick}>Force Update</button>
        <p>Random number: {Math.random()}</p>
      </div>
    );
  }
}

Опишите, как события обрабатываются в React.

В React события обрабатываются с помощью синтетических событий, также известных как SyntheticEvent. React абстрагирует нативные события браузера и упаковывает их в совместимый с разными браузерами объект SyntheticEvent, который более согласован и работает лучше.

Когда событие запускается в компоненте React, React отправляет SyntheticEvent соответствующему обработчику событий. Обработчик события получает SyntheticEvent в качестве аргумента, и вы можете получить доступ к свойствам и методам этого объекта, чтобы получить информацию о событии и его цели.

Пример:

import React from 'react';

class MyComponent extends React.Component {
  handleClick = (event) => {
    console.log('Button clicked!');
    console.log('Event type:', event.type);
    console.log('Target element:', event.target);
  };

  render() {
    return (
      <div>
        <button onClick={this.handleClick}>Click Me</button>
      </div>
    );
  }
}

Что такое чистый функциональный компонент в React?

Чистый функциональный компонент в React — это компонент, реализованный как чистая функция, принимающий реквизиты в качестве входных данных и возвращающий JSX-представление компонента. Чисто функциональные компоненты также известны как функциональные компоненты без состояния, поскольку они не имеют собственного состояния; они полагаются только на данные, полученные через реквизит.

Чтобы создать чистый функциональный компонент, вы определяете функцию, которая принимает props в качестве аргумента и возвращает JSX для визуализации компонента. Эти компоненты легко читать, тестировать и обслуживать, поскольку они не имеют внутреннего состояния и не полагаются на методы жизненного цикла.

Пример:

import React from 'react';

// Pure Functional Component
const Greeting = (props) => {
  return <h1>Hello, {props.name}!</h1>;
};

// Usage of the Pure Functional Component
const App = () => {
  return <Greeting name="John" />;
};

Какой второй аргумент можно опционально передать в setState и какова его цель?

Второй аргумент, который можно дополнительно передать в setState, — это функция обратного вызова, которая будет выполняться после обновления состояния и повторного рендеринга компонента. Эта функция обратного вызова часто используется для выполнения действий, зависящих от обновленного состояния и отображаемого компонента.

Цель второго аргумента — гарантировать, что код внутри обратного вызова запускается только после завершения обновления состояния и повторного рендеринга компонента с новым состоянием. Это полезно в ситуациях, когда вам нужно выполнить какое-то действие сразу после обновления состояния.

Пример:

import React from 'react';

class Counter extends React.Component {
  state = {
    count: 0,
  };

  handleIncrement = () => {
    // Update the state and execute a callback after the state is updated
    this.setState(
      (prevState) => ({ count: prevState.count + 1 }),
      () => {
        console.log('State updated:', this.state.count);
      }
    );
  };

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.handleIncrement}>Increment</button>
      </div>
    );
  }
}

Зачем вам нужно привязывать обработчики событий к этому?

В React вам необходимо привязать обработчики событий к this при использовании традиционного синтаксиса объявления функций в ES5 или если вы не используете стрелочные функции. Это связано с тем, что значение this внутри функции зависит от того, как эта функция вызывается.

Если вы не привяжете обработчик событий к this, вы можете столкнуться с проблемами, когда this становится неопределенным или ссылается на другой объект, что приводит к непредвиденному поведению или ошибкам.

При использовании стрелочных функций ES6 лексическая область действия стрелочных функций автоматически связывает текущее значение this, устраняя необходимость в явном связывании.

Пример (привязка в ES5):

import React from 'react';

class MyComponent extends React.Component {
  constructor() {
    super();
    // Bind the event handler to the component instance
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    // Event handler logic
  }

  render() {
    return <button onClick={this.handleClick}>Click Me</button>;
  }
}

Пример (автоматическая привязка в ES6):

import React from 'react';

class MyComponent extends React.Component {
  // No need to bind the event handler when using arrow functions
  handleClick = () => {
    // Event handler logic
  };

  render() {
    return <button onClick={this.handleClick}>Click Me</button>;
  }
}

Почему React использует SyntheticEvents?

React использует SyntheticEvents для обработки событий, поскольку они обеспечивают унифицированный и согласованный интерфейс для работы с событиями в разных браузерах. SyntheticEvents — это синтетические или искусственные события, то есть они создаются React и не являются нативными событиями браузера.

Абстрагируя собственные события браузера в SyntheticEvents, React может обрабатывать пулы событий и избегать потенциальных утечек памяти. Объединение событий в пул означает, что SyntheticEvents повторно используются и перерабатываются, что может привести к повышению производительности и снижению использования памяти по сравнению с созданием нового объекта события для каждого события.

Еще одно преимущество использования SyntheticEvents заключается в том, что они совместимы с разными браузерами, а это означает, что вам не нужно беспокоиться о несоответствиях обработки событий в конкретном браузере.

Как применить проверку реквизита в ReactJS?

Чтобы применить проверку свойств в ReactJS, вы можете использовать свойство propTypes или библиотеку prop-types. Свойство propTypes позволяет вам определять типы и требования к свойствам, которые должен получать компонент. Если компонент получает реквизиты, которые не соответствуют определенным типам или отсутствуют необходимые реквизиты, во время разработки в консоли будет отображаться предупреждение.

Использование propTypes без библиотеки prop-types (доступно до версии React 15.5):

import React from 'react';

class MyComponent extends React.Component {
  render() {
    return <div>{this.props.name}</div>;
  }
}

// Define propTypes for MyComponent
MyComponent.propTypes = {
  name: React.PropTypes.string.isRequired, // Required string prop
};

Использование библиотеки prop-types (React версии 15.5 и выше):

# Install the prop-types library
npm install prop-types
import React from 'react';
import PropTypes from 'prop-types';

class MyComponent extends React.Component {
  render() {
    return <div>{this.props.name}</div>;
  }
}

// Define propTypes for MyComponent using the prop-types library
MyComponent.propTypes = {
  name: PropTypes.string.isRequired, // Required string prop
};

Как создать Props Proxy для компонента HOC?

В React компонент высшего порядка (HOC) — это шаблон, который позволяет обернуть компонент дополнительными функциями. При создании HOC вы можете по-разному передавать реквизиты обернутому компоненту. Один из способов — использовать метод Props Proxy.

В Props Proxy HOC принимает компонент в качестве аргумента и возвращает новый компонент, который отображает исходный компонент с дополнительными реквизитами. Дополнительные реквизиты часто используются для предоставления дополнительных данных или функций обернутому компоненту.

Пример Props Proxy HOC:

import React from 'react';

// Higher-Order Component (HOC)
const withExtraProps = (WrappedComponent) => {
  return class extends React.Component {
    render() {
      // Add additional props to pass down to the wrapped component
      const extraProps = {
        extraData: 'Some extra data',
        extraFunction: () => {
          console.log('Extra function called');
        },
      };

      // Pass through the original props and the extra props to the wrapped component
      return <WrappedComponent {...this.props} {...extraProps} />;
    }
  };
};

// Component to be wrapped
const MyComponent = (props) => {
  return (
    <div>
      <p>{props.message}</p>
      {/* Accessing the extra props provided by the HOC */}
      <p>{props.extraData}</p>
    </div>
  );
};

// Wrap MyComponent using the withExtraProps HOC
const EnhancedComponent = withExtraProps(MyComponent);

// Usage of the EnhancedComponent
const App = () => {
  return <EnhancedComponent message="Hello from the App" />;
};

В чем разница между использованием конструктора и getInitialState в React?

В React constructor и getInitialState используются для инициализации состояния компонента, но их использование зависит от версии React.

constructor (React версии 16.3 и выше): в современных версиях React constructor используется для инициализации состояния и привязки обработчиков событий. Он вызывается перед монтированием компонента. Если вам нужно инициализировать состояние или привязать обработчики событий, используя традиционное объявление функции (синтаксис ES5), вы можете сделать это в файле constructor.

Пример:

import React from 'react';

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
    };
    // Binding event handler in the constructor (ES5 syntax)
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    // Event handler logic
  }

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.handleClick}>Increment</button>
      </div>
    );
  }
}

getInitialState (версия React до 16.3): в более старых версиях React (до 16.3) вы могли использовать getInitialState для инициализации состояния. Однако этот метод больше не рекомендуется, и вам следует использовать constructor для инициализации состояния во всех версиях React.

Пример (для более старых версий React):

import React from 'react';

class MyComponent extends React.Component {
  getInitialState() {
    return {
      count: 0,
    };
  }

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
      </div>
    );
  }
}

Когда важно передавать реквизиты в super() и почему?

При определении конструктора для компонента React на основе классов важно передать props в качестве аргумента методу super(). Это необходимо, потому что вызов super(props) инициализирует базовый класс (класс React.Component) и позволяет вам получить доступ к this.props внутри вашего компонента.

Если вы хотите получить доступ к this.props в конструкторе вашего компонента или в методах жизненного цикла, вам нужно сначала вызвать super(props), и только потом вы можете безопасно использовать this.props.

Пример:

import React from 'react';

class MyComponent extends React.Component {
  constructor(props) {
    super(props); // Pass props to the constructor of the base class
    console.log('Component props:', this.props); // Accessing props after calling super(props)
  }

  render() {
    return <div>{this.props.message}</div>;
  }
}

// Usage of MyComponent
const App = () => {
  return <MyComponent message="Hello from App" />;
};

Как условно добавить атрибуты в компоненты React?

В React вы можете условно добавлять атрибуты к компонентам, используя выражения JavaScript в JSX. Используя тернарные операторы, сокращение && или другие логические выражения, вы можете определить, следует ли добавлять атрибут или нет, исходя из некоторых условий.

Пример использования тернарного оператора:

import React from 'react';

const MyComponent = (props) => {
  const { isDisabled } = props;

  return (
    <div>
      {/* Conditional rendering of the disabled attribute */}
      <button disabled={isDisabled ? true : false}>Click Me</button>
    </div>
  );
};

Пример использования короткого замыкания &&:

import React from 'react';

const MyComponent = (props) => {
  const { isHidden } = props;

  return (
    <div>
      {/* Conditional rendering of the hidden attribute */}
      {isHidden && <p>This paragraph is hidden.</p>}
    </div>
  );
};

Когда бы вы использовали компонент StrictMode в React?

Компонент StrictMode в React используется во время разработки для выявления потенциальных проблем в коде приложения. Он помогает выявлять и исправлять небезопасные действия и устаревшие функции. Использование StrictMode не влияет на производственную сборку приложения; он только выдает предупреждения во время разработки.

Некоторые из проверок, выполненных StrictMode, включают:

  • Выявление использования небезопасных методов жизненного цикла
  • Обнаружение использования устаревшей ссылки на строку
  • Предупреждение об устаревшем использовании findDOMNode
  • Выделение потенциальных проблем с неожиданными побочными эффектами при рендеринге

Вы должны использовать StrictMode на этапе разработки вашего приложения, чтобы обеспечить лучшее качество кода и соблюдение лучших практик. Однако важно отметить, что StrictMode не предназначен для использования в рабочей среде и может вызвать некоторые неожиданные побочные эффекты из-за двойного рендеринга.

Пример использования StrictMode:

import React from 'react';

const App = () => {
  return (
    <React.StrictMode>
      {/* Your application components */}
    </React.StrictMode>
  );
};

Как бы вы подошли к исследованию медленного рендеринга приложений React?

Исследование и диагностика медленного рендеринга в приложении React может включать несколько шагов. Вот несколько стратегий, которые вы можете использовать:

  • Профилирование производительности. Используйте встроенные в React инструменты производительности, такие как React DevTools и Profiler API, для выявления узких мест производительности и компонентов, вызывающих повторную визуализацию. Profiler может показать вам, какие компоненты рендерятся чаще всего и потребляют больше всего ресурсов.
  • Используйте React.memo() и React.useMemo(): используйте React.memo() для функциональных компонентов и React.useMemo() для запоминания дорогостоящих вычислений и предотвращения ненужного повторного рендеринга.
  • Избегайте встроенных функций: будьте осторожны с объявлениями встроенных функций в JSX (например, onClick={() => handleButtonClick()}). Это может привести к повторному рендерингу в каждом цикле рендеринга. Вместо этого используйте свойства класса или React.useCallback() для запоминания обработчиков событий.
  • Сведите к минимуму повторную визуализацию компонентов. Убедитесь, что компоненты повторно визуализируются только при необходимости. Используйте класс shouldComponentUpdate, React.memo() или PureComponent для предотвращения ненужных повторных рендеров.
  • Избегайте ненужных обновлений состояния: убедитесь, что обновления состояния необходимы и соответствуют рендерингу компонента. Избегайте чрезмерных вызовов setState() или циклов.
  • Оптимизация дорогостоящих операций: оптимизация тяжелых вычислений и операций рендеринга. Если возможно, используйте методы виртуализации, чтобы уменьшить количество визуализируемых элементов.
  • Используйте вкладку «Производительность» в Chrome DevTools. Используйте вкладку «Производительность» в Chrome DevTools для записи и анализа профилей производительности. Определите области, в которых процессорное время и время рендеринга высоки.
  • Сетевой анализ: медленный рендеринг может быть вызван медленной выборкой данных. Анализируйте сетевые запросы с помощью инструментов разработчика браузера, чтобы обеспечить эффективное извлечение данных.
  • Разделение компонентов: подумайте о том, чтобы разбить большие компоненты на более мелкие, используя методы разделения кода React, чтобы загружать только то, что необходимо.
  • Проверьте сторонние библиотеки: некоторые сторонние библиотеки могут вызывать проблемы с производительностью. Используйте инструменты профилирования, чтобы проанализировать их влияние на ваше приложение.

Помните, что на производительность приложения React влияет множество факторов, а профилирование и измерение являются ключом к выявлению и устранению проблем с медленным рендерингом.

React перерисовывает все компоненты и подкомпоненты каждый раз, когда вызывается setState?

Нет, React не выполняет повторный рендеринг всех компонентов и подкомпонентов при каждом вызове setState. React спроектирован так, чтобы быть эффективным, и выполняет процесс, называемый «согласованием», чтобы определить, какие части дерева компонентов необходимо обновить.

Когда вы вызываете setState, React сравнивает предыдущее состояние с новым состоянием и определяет различия (также известные как «diff»). Затем будут обновлены только те компоненты, на которые повлияли изменения состояния, и их потомки в дереве компонентов. Компоненты, на которые не влияет изменение состояния, не будут повторно визуализированы.

Этот процесс согласования помогает свести к минимуму ненужные повторные рендеринги и оптимизировать производительность приложений React.

Однако важно правильно использовать setState и избегать чрезмерных обновлений состояния, чтобы обеспечить оптимальную производительность.

В чем разница между useCallback и useMemo на практике?

И useCallback, и useMemo — это хуки в React, используемые для оптимизации производительности функциональных компонентов путем запоминания значений и предотвращения ненужных повторных вычислений. Хотя у них есть сходство, они служат разным целям:

  • useCallback: этот хук используется для запоминания функций. Он возвращает запомненную версию функции, чтобы она не менялась при каждом рендеринге, пока не изменятся ее зависимости. Это полезно, когда вам нужно передать функцию дочерним компонентам, но вы хотите избежать ненужного повторного рендеринга этих дочерних компонентов.

Пример:

import React, { useCallback } from 'react';

const MyComponent = () => {
  const handleClick = useCallback(() => {
    console.log('Button clicked!');
  }, []);

  return <button onClick={handleClick}>Click Me</button>;
};
  • useMemo: этот хук используется для запоминания значений. Он возвращает запомненную версию значения, так что оно не будет пересчитываться, пока не изменятся его зависимости. Это полезно, когда у вас есть дорогостоящие вычисления или обработка данных, которые вы хотите кэшировать и повторно использовать при визуализации.

Пример:

import React, { useMemo } from 'react';

const MyComponent = ({ data }) => {
  const processedData = useMemo(() => {
    // Expensive computation on 'data' that we want to cache
    return data.map((item) => item * 2);
  }, [data]);

  return <div>{processedData.join(', ')}</div>;
};

Таким образом, useCallback используется для запоминания функций, а useMemo используется для запоминания значений. Они оба оптимизируют производительность, предотвращая ненужные повторные вычисления и повторную визуализацию.

Объясните, почему и когда вы будете использовать useMemo()?

Вы должны использовать useMemo(), когда у вас есть дорогостоящие вычисления или обработка данных, которые вы хотите кэшировать и повторно использовать при визуализации. Запоминая значение, возвращаемое useMemo(), React будет пересчитывать значение только тогда, когда изменятся зависимости, указанные во втором аргументе useMemo(). В противном случае он вернет кешированный результат.

Использование useMemo() помогает избежать ненужных и избыточных вычислений, особенно при работе с большими наборами данных или сложными вычислениями, которые не нужно повторно оценивать при каждом рендеринге.

Пример:

import React, { useMemo } from 'react';

const MyComponent = ({ data }) => {
  const processedData = useMemo(() => {
    // Expensive computation on 'data' that we want to cache
    return data.map((item) => item * 2);
  }, [data]);

  return <div>{processedData.join(', ')}</div>;
};

В этом примере processedData будет пересчитываться только при изменении реквизита data. При последующих рендерах с тем же data запомненное значение будет возвращено напрямую без повторной оценки функции сопоставления.

Разумное использование useMemo() может значительно повысить производительность вашего приложения React за счет сокращения ненужных перерасчетов.

Когда использовать useCallback, useMemo и useEffect?

useCallback, useMemo и useEffect — это три разных хука в React, и каждый служит определенной цели:

  • useCallback: используйте useCallback, когда хотите запомнить функцию. Он возвращает запомненную версию функции, предотвращая ее воссоздание при каждом рендеринге. Это полезно при передаче функции дочерним компонентам в качестве реквизита, чтобы избежать ненужного повторного рендеринга этих дочерних компонентов.
  • useMemo: используйте useMemo, когда хотите запомнить значение. Он возвращает запомненную версию значения, повторно вычисляя его только при изменении его зависимостей. Это полезно, когда у вас есть дорогостоящие вычисления или обработка данных, которые вы хотите кэшировать и повторно использовать при визуализации.
  • useEffect: используйте useEffect, когда вам нужно выполнить побочные эффекты в вашем компоненте, такие как выборка данных, подписки или ручное взаимодействие с DOM. useEffect вызывается после каждого рендера и может использоваться для управления жизненным циклом вашего компонента.

Чтобы решить, какой крючок использовать, примите во внимание следующие рекомендации:

  1. Используйте useCallback для оптимизации ссылок на функции в свойствах.
  2. Используйте useMemo для оптимизации дорогостоящих вычислений или обработки данных.
  3. Используйте useEffect для обработки побочных эффектов, таких как выборка данных, манипулирование DOM и подписки.

Всегда предоставляйте правильный массив зависимостей в качестве второго аргумента для этих ловушек, чтобы гарантировать, что они работают должным образом, и предотвратить ненужные повторные оценки и побочные эффекты.

Можете ли вы сделать наследование компонентов в React?

В React вы не можете достичь классического наследования (т. е. расширения базового компонента для создания дочернего компонента) так же, как в некоторых других языках программирования, таких как Java или C#. React продвигает композицию вместо наследования как основной способ построения иерархии компонентов.

Вместо классического наследования React поощряет композицию компонентов с использованием таких методов, как компоненты высшего порядка (HOC) и Render Props. Эти шаблоны позволяют повторно использовать функциональные возможности между компонентами без прямого наследования от родительского компонента.

Компоненты высшего порядка (HOC): HOC — это функции, которые принимают компонент в качестве аргумента и возвращают новый компонент с дополнительными реквизитами или поведением. Их можно использовать для обмена общей логикой или данными между несколькими компонентами.

Пример HOC:

const withLogging = (WrappedComponent) => {
  return class extends React.Component {
    render() {
      console.log('Component is rendered');
      return <WrappedComponent {...this.props} />;
    }
  };
};

const MyComponent = () => {
  return <div>Hello, World!</div>;
};

const EnhancedComponent = withLogging(MyComponent);

Реквизиты рендеринга: Реквизиты рендеринга — это шаблон, в котором компонент получает функцию в качестве реквизита и вызывает эту функцию для передачи данных или поведения своим дочерним элементам.

Пример реквизита рендеринга:

class MouseTracker extends React.Component {
  render() {
    return (
      <div onMouseMove={(e) => this.props.render(e.clientX, e.clientY)}>
        {/* Render the component that will use the mouse position */}
        {this.props.children}
      </div>
    );
  }
}

const App = () => {
  return (
    <MouseTracker render={(x, y) => <p>Mouse position: {x}, {y}</p>}>
      <h1>Mouse Tracker</h1>
    </MouseTracker>
  );
};

Используя эти шаблоны, вы можете достичь формы наследования компонентов в React, продвигая повторно используемый и компонуемый код.

В чем разница между инкрементным DOM и виртуальным DOM?

Incremental DOM и Virtual DOM — это методы, используемые в средах JavaScript для оптимизации производительности рендеринга, но они различаются по своим подходам:

Виртуальный дом:

  • Виртуальный DOM — это концепция, используемая такими фреймворками, как React. Это абстракция фактического DOM и легковесное представление компонентов пользовательского интерфейса в памяти.
  • Когда состояние компонента изменяется, React создает новое виртуальное дерево DOM, повторно отображая весь компонент и его поддерево. Затем это новое виртуальное дерево DOM сравнивается с предыдущим, чтобы найти различия (отличия).
  • Различия затем применяются к реальному DOM в пакетном режиме, что сводит к минимуму количество манипуляций с реальным DOM, повышая эффективность рендеринга.
  • Virtual DOM помогает уменьшить ненужные перекомпоновки и перерисовки в браузере, что приводит к повышению производительности.

Инкрементный DOM:

  • Incremental DOM — это концепция, используемая такими фреймворками, как Angular и Preact. Вместо создания нового виртуального дерева DOM и сравнения его с предыдущим, инкрементальный DOM напрямую генерирует инструкции для обновления реального DOM.
  • Когда состояние компонента изменяется, Incremental DOM вычисляет минимальный набор изменений, необходимых для обновления DOM, и применяет их постепенно. Это позволяет избежать накладных расходов на создание и сравнение целых виртуальных деревьев DOM.
  • Инкрементный DOM занимает меньше памяти и подходит для рендеринга больших, высокодинамичных приложений.
  • В отличие от Virtual DOM, который фокусируется на пакетном обновлении для повышения эффективности, Incremental DOM фокусируется на снижении накладных расходов, связанных с управлением и сравнением виртуальных представлений.

Таким образом, и Virtual DOM, и Incremental DOM — это методы оптимизации, направленные на минимизацию манипуляций с DOM и повышение производительности рендеринга. Виртуальный DOM создает облегченную абстракцию для эффективного сравнения и обновления реального DOM, в то время как инкрементный DOM напрямую вычисляет и применяет минимальные изменения к реальному DOM без создания отдельного виртуального представления.