9 вопросов на собеседовании, которые должен знать Senior React разработчик

2 года назад·1 мин. на чтение

Как разработчик на React, вы в конечном итоге испытаете желание сделать следующий большой шаг к роли Senior.

Некоторые разработчики застряли в роли junior или middle разработчика, даже когда уже набрали опыта. Конечно, опыт приходит со временем, но некоторые разработчики могут иметь мышление senior разработчика, но не изучать необходимые темы. Эта статья не будет содержать туториалы, но будет содержать общий обзор ответов, которые вы должны дать. Вот несколько очень распространенных вопросов на собеседовании, которые вам могут задать во время собеседования на React разработчика.

1. Можете ли вы описать ситуацию, когда вам пришлось оптимизировать React приложение, чтобы повысить его производительность? Как вы это сделали?

Как senior React разработчик, вы должны время от времени оптимизировать React приложение для повышения производительности. Понимание жизненного цикла и хуков React может помочь в этом. Некоторые способы оптимизации производительности приложения React могут включать:
  • Избегать ненужные повторные рендеры
  • Использование уникального идентификатора при отображении списков
  • Использование хуков, таких как useMemo и useCallback, для мемоизации функций
  • Ленивая загрузка

2. Как вы управляете состоянием в большом React приложении?

В React есть два типа состояний: локальное и глобальное состояние. Локальное состояние является эксклюзивным для области React компонента. Доступ к глобальному состоянию может получить любой из ваших компонентов. Некоторые распространенные библиотеки для управления состоянием в большом React приложении включают в себя
  • Redux
  • Recoil
  • Jotai
  • Rematch
  • и т.д.

Когда использовать состояние?

Представьте, что вы создаете приложение со списком дел в React. Вы хотите отслеживать список элементов, введенных пользователем, а также логическое значение, указывающее, загружает ли приложение данные из API в данный момент. Например, у вас может быть действие ADD_TODO, которое добавляет новый элемент списка дел в массив, и редьюсер, который соответствующим образом обновляет состояние. У вас также может быть действие SET_LOADING, которое обновляет состояние загрузки. Другим примером может быть корзина покупок, которая отслеживает товары в корзине, даже когда пользователь обновляет или покидает страницу. Если данные передаются только из глобальной переменной в компоненты приложения, можно также применить хук useContext. Это хорошо подходит для работы с темами пользовательского интерфейса приложения и с auth провайдерами.

3. Можете ли вы описать опыт работы со сложной структурой данных в React приложении? Как вы с этим справились?

Для работы со сложными структурами данных в приложении React может потребоваться использовать такие методы, как сопоставление вложенных данных, использование рекурсивных компонентов для рендеринга данных с несколькими уровнями вложенности и оптимизация производительности с помощью таких методов, как React.memo. Также может быть полезно использовать библиотеки, такие как lodash, для манипулирования и преобразования сложных структур данных. Очевидно, что существует множество способов обработки сложных структур данных в React. Ниже приведено несколько сценариев, в которых вам, возможно, придется более осторожно обращаться с обработкой и представлением данных.
  • Вложенные структуры данных, такие как дерево или граф
  • Большие наборы данных, которые необходимо отображать и обрабатывать в виде таблицы или списка
  • Структуры данных с несколькими уровнями вложенности, такие как объект JSON с несколькими слоями вложенных объектов и массивов
  • Постоянно меняющиеся структуры данных, такие как данные в реальном времени из прямой трансляции или подключения к веб-сокету

4. Как вы подходите к тестированию приложения React?

Важно иметь хорошую стратегию тестирования, чтобы убедиться, что ваше приложение React стабильно и работает правильно. Это может включать в себя комбинацию модульных тестов, интеграционных тестов и e2e тестов, а также таких методов, как снэпшот тестирование и TDD (разработка на основе тестирования).
  • Используйте встроенные утилиты тестирования React, такие как React Testing Library и Enzyme, для тестирования рендеринга и поведения компонентов
  • Напишите модульные тесты для отдельных компонентов React, чтобы убедиться, что они правильно работают в изоляции
  • Напишите интеграционные тесты, чтобы проверить взаимодействие между несколькими компонентами и убедиться, что они правильно работают вместе
  • Используйте платформу тестирования, такую как Jest, для запуска и организации тестов
  • Используйте снэпшот тестирование, чтобы убедиться, что отрисовка компонента не изменится неожиданно
  • Используйте разработку на основе тестирования (TDD) для написания тестов перед написанием кода реализации функции.
  • Используйте библиотеку для мокирования, такую как Sinon.js для имитации зависимостей в тестах
  • Напишите e2e тесты для тестирования приложения в целом, имитируя взаимодействие с пользователем в реальном браузере

5. Как вы обрабатываете асинхронные действия в приложении React?

Одним из способов является использование ключевых слов async и await, которые позволяют писать асинхронный код в синхронном стиле. Ниже приведен пример компонента, который выполняет асинхронный вызов API с помощью async и await:
import React, { useState, useEffect } from 'react';

function MyComponent() {
  const [data, setData] = useState(null);

  useEffect(() => {
    async function fetchData() {
      const response = await fetch('https://..../endpoint');
      const data = await response.json();
      setData(data);
    }
    fetchData();
  }, []);

  return (
    <div>
      {data ? (
        <div>{data.message}</div>
      ) : (
        <div>Loading...</div>
      )}
    </div>
  );
}
Еще один способ обработки асинхронных функций в React — использовать библиотеку, такую как axios или fetch, для выполнения вызовов API. Вот пример использования axios:
import React, { useState, useEffect } from 'react';
import axios from 'axios';

function MyComponent() {
  const [data, setData] = useState(null);

  useEffect(() => {
    async function fetchData() {
      const response = await axios.get('https://my-api.com/endpoint');
      setData(response.data);
    }
    fetchData();
  }, []);

  return (
    <div>
      {data ? (
        <div>{data.message}</div>
      ) : (
        <div>Loading...</div>
      )}
    </div>
  );
}

6. Можете ли вы рассказать разницу между презентационным и контейнерным компонентом в React?

В React презентационные компоненты связаны с тем, как все выглядит, в то время как компоненты-контейнеры связаны с тем, как все работает. Презентационные компоненты обычно отвечают за рендеринг элементов пользовательского интерфейса на экране. Они получают данные и обратные вызовы в качестве пропсов. Обычно они сосредоточены на рендеринге JSX и не знают о состоянии или действиях приложения. Ниже приведен пример презентационного компонента:
import React from 'react';

function Button(props) {
  return <button>{props.label}</button>;
}
Компоненты-контейнеры обычно отвечают за управление состоянием и действиями. Они содержат логику для получения данных, обработки пользовательского ввода и выполнения других задач. Они знают о состоянии и действиях приложения, а также передают данные и обратные вызовы презентационным компонентам в качестве пропсов. Ниже приведен пример компонента контейнера:
import React, { Component } from 'react';
import Button from './Button';

class Form extends Component {
  state = {
    name: '',
  };

  handleChange = (event) => {
    this.setState({ name: event.target.value });
  };

  handleSubmit = (event) => {
    event.preventDefault();
    // отправка формы
  };

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" value={this.state.name} onChange={this.handleChange} />
        </label>
        <Button label="Submit" />
      </form>
    );
  }
}
Разделение презентационных и контейнерных компонентов может помочь упростить понимание, тестирование и обслуживание кода, отделив проблемы внешнего вида от того, как все работает.

7. Можете ли вы описать, как бы вы реализовали функциональность пагинации в приложении React?

Вот один из способов реализовать пагинацию в React приложении:
  • Определите общее количество страниц, которые вам нужны, исходя из объема имеющихся у вас данных и количества элементов, которые вы хотите отобразить на странице.
  • Добавьте переменную состояния page в компонент для отслеживания текущей страницы.
  • Напишите функцию, которая извлекает данные для определенной страницы и обновляет состояние компонента новыми данными.
  • Визуализируйте пользовательский интерфейс нумерации страниц, который может включать кнопки для перехода к следующей и предыдущей страницам, а также раскрывающийся список для выбора определенной страницы.
  • Добавьте обработчики событий для элементов пользовательского интерфейса пагинации, которые вызывают функцию fetch с соответствующим номером страницы.
Вы также можете даже использовать библиотеки пользовательского интерфейса, такие как Material UI, чтобы ускорить разработку, которая дает вам базовые компоненты для создания функций с разбиением на страницы.

8. Как вы обрабатываете роутинг на стороне клиента в приложении React?

Существует несколько способов обработки роутинга на стороне клиента в приложении React. Одним из популярных способов является использование библиотеки react-router-dom, которая предоставляет компонент <Router> для обработки роутинга и набор компонентов <Route> для определения роутов в приложении. Ниже приведен пример того, как можно использовать react-router-dom для обработки роутинга на стороне клиента в приложении React: Установите библиотеку react-router-dom.
npm install react-router-dom
Импортируйте компоненты <Router> и <Route> из react-router-dom.
import { BrowserRouter as Router, Route } from 'react-router-dom';
Оберните приложение компонентом <Router>.
<Router>
  <App />
</Router>
Определите свои маршруты с помощью компонента <Route>. Компонент <Route> принимает проп path, указывающий путь для роута, и проп component, указывающий компонент для визуализации при сопоставлении роута.
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/users/:id" component={User} />
Компонент <Route> отобразит указанный компонент, когда текущий URL-адрес совпадет с путем роута. Вы можете использовать проп exact, чтобы указать, что маршрут должен быть сопоставлен только в том случае, если путь точно совпадает с текущим URL-адресом. Вы также можете использовать компонент <Link> из react-router-dom для создания ссылок, которые перемещаются между маршрутами в вашем приложении.
import { Link } from 'react-router-dom';
...
<Link to="/about">About</Link>
Подробнее о React Router читайте в серии статей:
  1. Основы React Router
  2. Продвинутые определения маршрутов
  3. Управление навигацией
  4. Подробно о роутерах

9. Можете ли вы рассказать о преимуществах использования React Context API?

React Context API — отличная альтернатива передаче данных без использования пропсов родительского компонента. Это может быть особенно полезно в тех случаях, когда у вас есть глубоко вложенная структура компонентов или если вы хотите передать данные компоненту, который находится на много уровней вниз по дереву. Некоторые преимущества использования React Context API включают в себя:

Устраняет prop drilling

С помощью Context API вы можете избежать необходимости передавать пропсы через несколько уровней компонентов, что может стать утомительным и затруднить чтение и поддержку кода.

Упрощает совместное использование состояния между компонентами

Если у вас есть состояние, которое необходимо совместно использовать между несколькими компонентами, API контекста может упростить это без необходимости поднимать состояние до общего предка.

Повышает производительность

Так как Context API не полагается на React Virtual DOM для передачи данных между компонентами, он может быть более эффективным, чем использование пропсов. Это может быть особенно полезно в тех случаях, когда вы передаете большие объемы данных или часто выполняете повторный рендеринг.

Увеличивает повторное использование кода

Если у вас есть компоненты, которым требуется доступ к одним и тем же данным, вы можете использовать Context API, чтобы сделать эти данные доступными для них, что может упростить повторное использование этих компонентов в разных частях вашего приложения.

Вопросы и ответы React собеседования 2023 - Часть 1

2 года назад·6 мин. на чтение

Актуальный список вопросов и ответов по ReactJS на собеседовании 2023

1. Как работает React?

React создает виртуальный DOM. Когда состояние компонента изменяется, он сначала запускает алгоритм сравнения, который идентифицирует, что изменилось в виртуальном DOM. Второй шаг — согласование (reconciliation), при котором DOM обновляется результатами из сравнения.

2 Каковы достоинства использования React?

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

3. В чем разница между презентационным компонентом и компонентом-контейнером?

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

4. Каковы различия между компонентом класса и функциональным компонентом?

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

5. В чем разница между состоянием и пропсами?

Состояние — это структура данных, которая начинается со значения по умолчанию при монтировании компонента. Он может видоизменяться со временем, в основном в результате пользовательских событий. Пропсы (сокращение от properties, props) — это конфигурация компонента. Они получены сверху из компонента родителя и неизменяемы (иммутабельны). Компонент не может изменять свои пропсы. Функции обратного вызова также можно передавать в качестве пропсов.

6. Какие существуют методы жизненного цикла?

  • componentWillMount (устаревший) — чаще всего используется для настройки приложения в корневом компоненте.
  • componentDidMount — здесь вы можете сделать всю настройку, которую вы не смогли бы сделать без DOM, и начать получать все необходимые вам данные. Кроме того, если вы хотите настроить прослушиватели событий и т. д., этот хук жизненного цикла — хорошее место для этого.
  • componentWillReceiveProps (устаревший) — этот жизненный цикл действует на определенные изменения пропсов, чтобы вызвать переходы состояний.
  • shouldComponentUpdate — если вы беспокоитесь о потраченных впустую рендерах, shouldComponentUpdate — отличное место для повышения производительности, поскольку оно позволяет предотвратить повторный рендеринг, если компонент получает новый проп. shouldComponentUpdate всегда должен возвращать логическое значение, и на его основе будет определяться, будет ли компонент перерисован или нет.
  • componentWillUpdate (устаревший) — используется редко. Его можно использовать вместо componentWillReceiveProps для компонента, у которого также есть shouldComponentUpdate (но нет доступа к предыдущим значениям пропсов).
  • componentDidUpdate — также обычно используется для обновления DOM в ответ на изменение пропсов или состояния.
  • componentWillUnmount — позволяет отменить любые исходящие сетевые запросы или удалить все прослушиватели событий, связанные с компонентом. Вызывается перед размонтированием компонента.

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

Хуки позволяют вам использовать больше функций React без использования классов. Первый хук, с которым вы, скорее всего, столкнетесь, это useState. useState — это хук, который позволяет добавлять состояние React к компонентам-функциям. Он возвращает массив с геттером и сеттером. Синтаксис выглядит так:
const [count, setCount] = React.useState(0);

<button onClick={() => setCount(count + 1)}>Increase Count</button>;
Эквивалентом при использовании компонента класса будет.
this.state = {
  count: 0,
};

<button onClick={() => this.setState({ count: this.state.count + 1 })}>
  Increase Count
</button>;
Следующий хук, с которым вы, скорее всего, столкнетесь, это useEffect. Хук эффектов позволяет выполнять побочные эффекты в функциональных компонентах. Передача пустого массива в качестве второго аргумента useEffect эквивалентна использованию componentDidMount. Если вы передадите значение в массив, функция useEffect будет вызываться только при обновлении значения в массиве.
useEffect(() => {
  // делаем что-то, когда компонент монтируется
}, []);
Подробнее о хуках:

8. Где стоит выполнять AJAX/API запрос в классовом React компоненте?

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

9. Что такое управляемые компоненты?

В HTML элементы формы, такие как <input>, <textarea> и <select>, обычно поддерживают свое собственное состояние и обновляют его на основе ввода пользователя. Когда пользователь отправляет форму, значения из упомянутых элементов отправляются вместе с формой. С React это работает иначе. Компонент, содержащий форму, будет отслеживать значение ввода в своем состоянии и будет повторно отображать компонент каждый раз, когда запускается функция обратного вызова, например, onChange, когда состояние будет обновлено. Элемент формы ввода, значение которого управляется React таким образом, называется управляемым компонентом. Видео про управляемые компоненты.

10. Для чего в React используются рефы?

Рефы используются для получения ссылки на DOM узел или экземпляр компонента в React. Хорошими примерами использования ссылок являются управление фокусом/выбором текста, запуск императивной анимации или интеграция со сторонними DOM библиотеками.

11. Что такое компоненты высшего порядка?

Компонент высшего порядка (Higher Order Component, HOC) — это компонент, который принимает компонент и возвращает новый компонент. HOC позволяют повторно использовать код и инициализировать компонент. Наиболее популярным HOC является функция connect из Redux. Помимо простого совместного использования библиотек и простой композиции, HOC — лучший способ хранить общее поведение между React компонентами. Если вы обнаружите, что пишете много кода в разных местах, который делает одно и то же, вы можете реорганизовать этот код в многоразовый HOC. Видео по теме:

12. Какие преимущества дает использование стрелочных функций?

  • Безопасность области действия: до появления стрелочных функций каждая новая функция определяла собственное значение this (новый объект в случае конструктора, undefined в вызовах функций в строгом режиме или базовый объект, если функция вызывается как «метод объекта» и т. д.). Стрелочная функция не создает собственного this, используется значение this окружающего контекста выполнения.
  • Компактность: стрелочные функции легче читать и писать.
  • В классовых React компонентах стрелочные функции удобнее использовать для того чтобы избежать байндинга методов при передаче их в качестве функций обратного вызова.

13. Как бы вы предотвратили рендеринг классового компонента?

Возврат null из метода рендеринга компонента означает, что ничего не будет отображаться, но это не влияет на срабатывание методов жизненного цикла компонента. Если количество повторных рендеров компонента является проблемой, доступны два варианта. Ручная реализация проверки в методе жизненного цикла shouldComponentUpdate.
shouldComponentUpdate(nextProps, nextState){
  const allowRender = true;
  // Делаем здесь некоторую проверку и назначаем решение в allowRender
  return allowRender
}
Или использовать React.PureComponent вместо React.Component. React.PureComponent реализует shouldComponentUpdate() с поверхностным сравнением пропсов и состояний. Это позволяет избежать повторного рендеринга компонента со значениями просов и состояний, которые не поменялись.

14. Что такое key при рендеринге списка и для чего он нужен?

Key помогают React определить, какие элементы были изменены, добавлены или удалены. Ключи должны быть даны элементам внутри массива, чтобы однозначно идентифицировать элементы. Лучший способ выбрать ключ — использовать строку, которая однозначно идентифицирует элемент списка среди его соседей, например, id. Чаще всего вы будете использовать идентификаторы из ваших данных в качестве ключей. Если у вас нет стабильных идентификаторов для отображаемых элементов, вы в крайнем случае можете использовать индекс элемента в качестве ключа. Не рекомендуется использовать индексы для ключей, т.к. это может привести к неверному отображению элементов в случае их удаления или изменения порядка. Также key можно использовать для пересоздания компонентов.

15. Для чего нужно вызывать super(props)?

Конструктор дочернего класса не может использовать this до тех пор, пока не будет вызвана функция super(). Кроме того, конструкторы классов ES2015 должны вызывать super(), если они являются подклассами. Причина передачи пропса в super() заключается в том, чтобы вы могли получить доступ к this.props в конструкторе. Хочешь узнать больше? Еще вопросы с собеседований.