Перейти к основному содержимому

React

Что такое React?

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

Реактивность React

React не предоставляет полноценную реактивную систему "из коробки", например: Vue.js. Реактивность в React достигается через систему состояний (state), пропсов (props), механизмы жизненного цикла компонентов и hooks. Это требует от разработчиков явного управления реактивностью, что делает React более гибким, но также требует от них больше работы.

Виртуальный DOM

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

key в React

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

Почему важен key?

  • Процесс "согласования": React использует алгоритм "согласования" (reconciliation), чтобы определить, какие части дерева компонентов должны быть обновлены. Проп key позволяет React точно сопоставить элементы между старым и новым деревьями, что улучшает производительность и эффективность обновления интерфейса пользователя
  • Уникальность ключей: Лучшим способом выбора ключа является использование строки, которая уникально идентифицирует элемент среди его соседей. Обычно это ID из данных. Если у элементов нет стабильных ID, можно использовать индекс элемента как последнее средство, но это может негативно сказаться на производительности и вызвать проблемы с состоянием компонента

Как правильно использовать key?

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

Механизм Reconciliation

"Reconciliation" (реконсиляция) в React — это процесс сравнения нового и старого виртуальных DOM для определения минимальных изменений, необходимых для обновления реального DOM. Процесс включает следующие шаги:

  1. Создание нового виртуального DOM: При изменении состояния компонента создается новый виртуальный DOM.

  2. Сравнение с предыдущим виртуальным DOM: Используется алгоритм diffing для выявления различий между новым и старым виртуальными DOM.

  3. Определение изменений: Идентификация добавленных, удаленных или перемещенных элементов. Здесь ключи (keys) играют критическую роль, поскольку они помогают React точно определить, какие элементы были изменены, добавлены или удалены, благодаря их уникальности и стабильности порядка.

  4. Применение изменений к реальному DOM: Эффективное обновление реального DOM согласно определенным изменениям. Ключи также используются на этом этапе, чтобы гарантировать, что изменения применяются к правильным элементам и что порядок элементов сохраняется.

  5. Использование ключей: Для использования ключей в React, они должны быть указаны в качестве свойства key у каждого дочернего элемента списка. Это позволяет React точно сопоставлять элементы между старым и новым виртуальными DOM, что критически важно для эффективного обновления интерфейса.

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

React Fiber

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

Что такое хуки в React?

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

Какие хуки знаешь?

1. useState

  • Особенность: Позволяет добавлять локальное состояние в функциональные компоненты.
  • Пример использования: Управление простыми данными, такими как текст ввода пользователя или переключатели.

2. useEffect

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

3. useContext

  • Особенность: Позволяет избежать проп-дриллинга (передача props через цепочку компонентов) путем прямого доступа к значению контекста.
  • Пример использования: Глобальные темы, языковые настройки, аутентификация пользователя.

4. useReducer

  • Особенность: Предназначен для управления сложными состояниемми, особенно когда требуется применять редуктор для преобразования состояния.
  • Пример использования: Формы, счетчики, игры, где состояние меняется в результате действий пользователя.

5. useCallback

  • Особенность: Возвращает мемоизированную версию колбэка, который изменяется только если изменяются зависимости.
  • Пример использования: Передача колбэков в дочерние компоненты, оптимизация производительности.

6. useMemo

  • Особенность: Возвращает мемоизированное значение, которое пересчитывается только при изменении зависимостей.
  • Пример использования: Вычисление дорогостоящих вычислений, оптимизация производительности.

7. useRef

  • Особенность: Создает ссылку на элемент DOM или сохраняет значение в памяти, которое не вызывает перерисовку при его изменении.
  • Пример использования: Фокусировка на элементах формы, измерение размеров элементов, сохранение текущего фокуса.

8. useImperativeHandle

  • Особенность: Вызывается внутри дочернего компонента, чтобы определить, какие свойства и методы будут доступны для родительского компонента через ref.
  • Пример использования: Интерактивность с дочерними компонентами, создание пользовательских рефов.

9. useLayoutEffect

  • Особенность: Синхронная версия useEffect, которая выполняется перед отрисовкой браузера. Используется для чтения DOM и синхронной обработки данных перед отображением пользователю.
  • Пример использования: Изменение стиля элементов до того, как страница отрендерится, чтение размеров элементов.

10. useDebugValue

  • Особенность: Добавляет строку в инспектор React DevTools для хука, что может быть полезно для отладки.
  • Пример использования: Легкая идентификация источника данных в DevTools.

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

Правила и принципы хуков

  1. Любой хук должен начинаться use
  2. Используйте хуки только на верхнем уровне (Не используйте хуки внутри циклов, условных операторов или вложенных функций)
  3. Вызывайте хуки только из React-функций (Вызывать хуки из функционального компонента React или из пользовательского хука )

Отличие useLayoutEffect от useEffect

useLayoutEffect

  • СинхронностьuseLayoutEffect выполняется синхронно, то есть весь код внутри этого хука выполняется сразу после всех изменений в DOM, но перед тем, как браузер начинает процесс повторной отрисовки.
  • Замена componentWillMount: Этот хук часто используется для выполнения действий, аналогичных тому, что делал метод жизненного цикла componentWillMount в классовых компонентах React. Это позволяет выполнять важные действия, такие как измерение размеров элементов или подготовка данных, до того, как пользователь увидит обновления на странице.
  • Примеры использования: Измерение размеров элементов, подготовка данных, которые должны быть готовы до отрисовки, оптимизация производительности путем минимизации "задержки" видимости изменений для пользователя.

useEffect

  • АсинхронностьuseEffect работает асинхронно и запускается после того, как браузер завершил отрисовку. Это делает его идеальным для выполнения операций, которые не влияют на взаимодействие пользователя с интерфейсом, например, загрузка данных.
  • Примеры использования: Загрузка данных, подписка на события, которые не должны блокировать отрисовку, выполнение операций, не требующих немедленного выполнения до отрисовки.

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

HOC

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

Что такое memo?

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

ErrorBoundary

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

Как работает ErrorBoundary

ErrorBoundary оборачивает другие компоненты и перехватывает любые ошибки, которые происходят в них или в их дочерних компонентах. Если компонент выбрасывает исключение, ErrorBoundary перехватывает это исключение и рендерит запасной UI, указанный в свойстве fallback.

PureComponent

Компоненты в реакте ререндеряться, если ререндериться родитель. Чтобы избежать лишних рендоров можно в классовом React наследоваться на компоненте не от React.Component, а от React.PureComponent, а в функциональном обернуть компонент в React.memo. Благодаря этому компонент будет ререндерится, если изменятся пропсы (не глубокое сравнение) или состояние в самом компоненте.

Контролируемые и неконтролируемые компоненты в React?

Управляемые компоненты в React контролируют данные формы через состояние компонента, используя setState или useState, что позволяет легко реализовать валидацию, отключение кнопок до проверки всех полей и обработку форматов ввода. Пример:

import React, { useState } from 'react';

function ControlledInput() {
const [name, setName] = useState('');

function handleNameChange(event) {
setName(event.target.value);
}

function handleSubmit(event) {
event.preventDefault();
console.log(name);
}

return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" value={name} onChange={handleNameChange} />
</label>
<button type="submit">Submit</button>
</form>
);
}

Неуправляемые компоненты хранят данные формы в DOM, используя рефы для чтения значений. Это может быть удобно при интеграции с кодом, не связанным с React, но может привести к потере чистоты кода. Пример:

import React, { useRef } from 'react';

function UncontrolledInput() {
const nameInput = useRef();

function handleSubmit(event) {
event.preventDefault();
console.log(nameInput.current.value);
}

return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" ref={nameInput} defaultValue="" />
</label>
<button type="submit">Submit</button>
</form>
);
}

Что такое children и props children?

Когда вы хотите явно указать, что компонент должен принимать дочерние элементы, вы можете использовать children в качестве имени свойства.

function Container({ children }) {
return <div className="container">{children}</div>;
}

function App() {
return (
<Container>
<h1>Hello, world!</h1>
<p>Welcome to my app.</p>
</Container>
);
}

Использование props.children

React автоматически добавляет props.children к каждому компоненту, поэтому вам не обязательно явно указывать children в качестве имени свойства. Вот тот же пример, но используя props.children:

function Container(props) {
return <div className="container">{props.children}</div>;
}

function App() {
return (
<Container>
<h1>Hello, world!</h1>
<p>Welcome to my app.</p>
</Container>
);
}

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

Что такое Outlet?

Outlet в React Router — это место, куда React Router помещает страницу, которую нужно показать, основываясь на текущем URL. Если у вас есть главная страница и подстраницы, например, "/about" и "/contact", вы можете использовать Outlet для показа содержимого этих страниц внутри общего шаблона вашего сайта.

children в React — это способ передачи дочерних элементов (которые могут быть элементами, компонентами или данными) от родительского компонента к дочернему. Это позволяет создавать более гибкие и адаптивные компоненты, так как родительский компонент может определять, что именно будет отображаться внутри него

Lazy Loading

Lazy loading в React позволяет откладывать загрузку компонентов до момента их необходимости, что улучшает производительность приложения. Для реализации lazy loading используется React.lazy() для динамического импорта компонентов и Suspense для управления процессом ожидания загрузки компонентов. Suspense позволяет задерживать рендеринг до тех пор, пока не будут загружены все необходимые компоненты, показывая пользователю индикатор загрузки или запасной контент. Этот подход упрощает работу с асинхронными операциями и улучшает пользовательский опыт за счет более плавной загрузки контента

Wrapper

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

import React from 'react';

// Wrapper компонент, который оборачивает другой компонент и добавляет к нему стиль
const StyledWrapper = ({ children }) => {
return <div style={{ padding: '20px', backgroundColor: '#f5f5f5' }}>{children}</div>;
};

export default StyledWrapper;
import React from 'react';
import StyledWrapper from './StyledWrapper';

// Компонент, который будет оборачиваться
const ContentComponent = () => {
return <div>Это мой контент</div>;
};

// Использование StyledWrapper для оборачивания ContentComponent
const App = () => {
return (
<StyledWrapper>
<ContentComponent />
</StyledWrapper>
);
};

export default App;

React элемент и React компонент

  • React Элементы являются неизменяемыми объектами, описывающими, что должно быть отображено на экране. Они могут содержать другие элементы и описывают тип элемента (например, <div>), его свойства (например, className) и дочерние элементы. Элементы создаются через JSX или с помощью React.createElement() и не имеют собственного состояния или методов.

  • React Компоненты могут быть функциональными или классовыми и отвечают за создание и возвращение элементов. Компоненты принимают входные данные (props) и возвращают элементы (или другие компоненты). Компоненты могут иметь состояние и методы, что позволяет им реагировать на изменения и выполнять различные действия.

Жизненные циклы компонентов

  1. Инициализация

    • Установка начального состояния и параметров по умолчанию.
  2. Монтирование

    • Подготовка к монтированию в DOM.
      • componentWillMount
    • Монтирование в DOM.
      • componentDidMount
  3. Обновление

    • Обновление компонента:
      • Изменение свойств (props)
        • shouldComponentUpdate
        • componentWillUpdate
        • componentDidUpdate
    • Изменение состояния (setState)
  4. Размонтирование

    • Удаление компонента из DOM.
      • componentWillUnmount

Что такое чанки?

Чанки в контексте React относятся к технике разделения кода на меньшие части, которые могут быть загружены асинхронно по мере необходимости. Это позволяет оптимизировать производительность приложения, уменьшая время первоначальной загрузки и улучшая восприятие работы приложением пользователями. Чанки создаются с помощью динамического импорта (import()) и могут быть управляемыми с помощью компонентов React.lazy и Suspense.

StoryBook

Storybook — это инструмент JavaScript для организации пользовательских интерфейсов, который делает процессы разработки компонентов, тестирования и создания документации более эффективными и простыми. Он поддерживает множество фреймворков и библиотек для веб-приложений, в том числе React, Vue и Angular.

Redux

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

  • Store (хранит состояние),
  • Reducers (обрабатывают действия и обновляют состояние)
  • Actions (описывают, что произошло).

Хуки Redux

  • useDispatch: возвращает функцию dispatch, которую можно использовать для отправки действий в хранилище Redux. Это альтернатива connect для диспатчинга действий.

  • useSelector: позволяет компоненту подписываться на определённые части состояния хранилища Redux. Этот хук принимает функцию селектора, которая извлекает нужные данные из состояния хранилища.

  • useStore: позволяет получить прямой доступ к хранилищу Redux. Это может быть полезно для чтения состояния или диспатчинга действий без использования useSelector или useDispatch.

Redux Thunk

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

import { createAsyncThunk } from '@reduxjs/toolkit';

// Создание асинхронного действия
export const fetchUserById = createAsyncThunk('users/fetchByIdStatus', async (userId, thunkAPI) => {
const response = await userAPI.fetchById(userId);
return response.data;
});

// Использование в компоненте
const { data: user, error } = useSelector(state => state.user);
const dispatch = useDispatch();

useEffect(() => {
dispatch(fetchUserById(1))
.unwrap()
.then(
user => console.log(user),
error => console.error('Failed to fetch user:', error)
);
}, [dispatch]);

Action, Payload

Action в Redux — это объект, описывающий, что должно произойти в приложении. Он состоит из type (типа действия) и payload (полезной нагрузки), где payload содержит конкретные данные, связанные с этим действием. Когда действие диспатчивается, соответствующий редьюсер обновляет состояние приложения на основе этого действия.

Разница между Redux и Context?

  • Redux лучше подходит для больших приложений, где нужно строгое управление состоянием с использованием промежуточного ПО и DevTools. Состояние хранится в одном объекте (store), и обновляется через действия (actions) и редьюсеры (reducers), следуя принципу однонаправленного потока данных (Flux).

  • React Context API лучше подходит для небольших и средних приложений, где управление состоянием менее сложное. Позволяет передавать данные по дереву компонентов без явной передачи через пропсы, создавая "контекстное" состояние, доступное для компонентов-потребителей. Подходит для глобальных значений, таких как стили, локализация, темы, но не для сложного глобального состояния.

React Portal?

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

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

Для работы с порталами необходимо предварительно определить точку монтирования в DOM, после чего можно безопасно использовать React Portals для создания сложных пользовательских интерфейсов

Open Graph

Open Graph (OG) - это протокол метаданных, который позволяет определить, как информация о странице или объекте должна быть отображена при ее представлении в социальных сетях и других платформах. Он был разработан Facebook для определения наиболее важных атрибутов (например, заголовок, описание, изображение) для отображения на платформе в социальном графе пользователя.

RTK query

RTK Query упрощает работу с API и кэширование данных, автоматически кэшируя ответы и сокращая запросы к серверу. Он использует "API slice" для организации запросов и генерирует хуки React для выполнения запросов и управления состоянием данных. Поддерживает автообновление и инвалидацию кэша для актуализации данных.

React query

React Query — это инструмент для управления состоянием и кэширования данных в React, упрощающий работу с удаленными запросами к API. Основные компоненты:

  • Query: Отражает запрос к серверу, включая статус, данные и ошибки.
  • Mutation: Операция для изменения данных на сервере, с информацией о статусе и результатах.
  • QueryCache: Хранит кэшированные данные запросов, автоматически управляя их обновлением и инвалидацией.