Собеседование ReactJS - вопросы и ответы

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

В‌ ‌этой ‌статье рассмотрим 10 вопросов, которые могут встретиться на собеседовании по ReactJS на позицию React или frontend разработчика.

Подписывайтесь на наш Boosty и задавайте ваши вопросы через форму. Я запишу видео-ответы или статьи, где вы сможете получить быстрый ответ на интересующие именно вас вопросы. Если вы начинающий фронтенд-разработчик, это лучшая возможность получить ответ на вопрос, который вы стеснялись задать коллегам. А еще на Boosty вас уже ожидают эксклюзивные статьи и видео на актуальные темы. Итак, теперь рассмотрим вопросы с собеседований:

Управляемые и неуправляемые компоненты

Элемент называется управляемым, если его значение контролирует React. Эта тема связана с такими HTML элементами как input, textarea, select. Обычно эти элементы сами управляют своим состоянием и сами обновляются когда пользователь вводит данные. Это неуправляемые компоненты - они хранят свои данные прямо в DOM. Чтобы прочитать их значения, используются рефы. Для того чтобы сделать управляемый компонент, нужно чтобы значение этих элементов хранилось именно в состоянии React компонента, т.е. управлялось через setState/useState, таким образом состояние React-компонента становится единственным источником правды для этих элементов.
// Управляемый компонент
import React, { useState } from 'react'

export 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>
  )
}
// Неуправляемый компонент
import React, { useRef } from 'react'

export 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>
  )
}
Исходный код

Что такое контекст в React (React Context)?

Контекст позволяет передавать данные через дерево компонентов без необходимости передавать пропсы на промежуточных уровнях. Обычно данные в React-приложении передаются от родителя к дочернему компоненту через пропсы (Как передавать данные между компонентами в ReactJS). Но когда компонентов много или множество компонентов должны быть изменяемы в зависимости от темы - то передавать пропсы для такого случая очень сложно. Для решения этой проблемы можно использовать контекст. Контекст предоставляет способ делиться такими данными между компонентами без необходимости явно передавать пропсы через каждый уровень дерева компонентов. Создаем контекст.
// context.js
import { createContext } from 'react'

export const Context = createContext()
Оборачиваем пользователей этого контекста в тег <Context.Provider /> и передаем внего значения через проп value.
// Component.js
import { useState } from 'react'
import { Context } from './context'

import Parent from './Parent'

export const Component = () => {
  const [name, setName] = useState()

  return (
    <Context.Provider value={{ name, setName }}>
      <Parent />
    </Context.Provider>
  )
}
В компоненте Parent вызываем функцию setName из контекста.
// Parent.js
import { useContext } from 'react'

import { Context } from './context'
import Child from './Child'

export const Parent = () => {
  const { setName } = useContext(Context)

  const handleNameChange = (event) => {
    setName(event.target.value)
  }

  return (
    <>
      <input
        type="text"
        onChange={handleNameChange}
      />

      <Child />
    </>
  )
}
В компоненте Child читаем из контекста значение name.
// Child.js
import { useContext } from 'react'
import { Context } from './context'

export const Child = () => {
  const { name } = useContext(Context)

  return (
    <span>Name is: {name || '<Not set>'}</span>
  )
}

Что такое порталы в React?

Порталы позволяют рендерить дочерние элементы в DOM-узел, который находится вне DOM-иерархии родительского компонента. Порталы особенно спасают когда в родительском компоненте заданы стили overflow: hidden или z-index, и нужно, чтобы дочерний элемент визуально выходил за рамки своего контейнера. Это диалоги, модальные окна или всплывающие подсказки.

Что такое refs в React и в чем их важность?

Рефы дают возможность получить доступ к DOM-узлам или React-компонентам. Ситуации, в которых использование рефов является оправданным:
  • Управление фокусом, выделение текста или воспроизведение медиа;
  • Императивный вызов анимаций;
  • Интеграция со сторонними DOM-библиотекам;
  • и др.
В рефах можно хранить любое значение, не обязательно ссылку на элемент. Изменение поля current не приводит к реренденру компонента.
import React, { useRef } from 'react'

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

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

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

Что такое key в React и в чем их важность?

Key - это специальный строковый атрибут, который нужно указывать при создании списка элементов. Если мы хотим показать компоненты в списке то нужно указать эти ключи явно, чтобы помочь React определять, какие элементы были изменены, добавлены или удалены. Далее React сопоставляет элементы массива с течением времени. Если у элемента есть id то лучше всего использовать именно это значение в качестве ключа. В крайнем случае можно использовать индекс элемента как ключ. Если порядок элементов может поменяться, использовать индексы в качестве ключей крайне не рекомендуется. Это негативно скажется на производительности и может вызвать проблемы с состоянием компонента. Еще один сценарий использования key

Render props

Render prop относится к возможность разделять код между компонентами с помощью пропа, значение которого является функцией. Render prop — функция, которая сообщает компоненту, что необходимо рендерить.
// Example.jsx
import React, { useState } from "react";
import Button from "react-bootstrap/Button";

import { CartIcon } from "./CartIcon/CartIcon";

const renderBadge = (count) => {
  return (
      <div>{count}</div>
  );
};

export const Example = () => {
  const [cart, setCart] = useState([]);

  const handleClick = () => {
    console.log("Cart Item clicked");
  };

  return (
    <CartIcon
      renderBadge={() => renderBadge(cart.length)}
      onClick={handleClick}
    />
  );
};
// CartIcon.jsx
import React from "react";
import { MdShoppingCart } from "react-icons/md";

export const CartIcon = ({ renderBadge = () => null, onClick }) => {
  return (
    <div onClick={onClick}>
      <div>{renderBadge()}</div>
      <MdShoppingCart />
    </div>
  );
};
Исходный код

Что такое Redux?

Redux - это стэйт менеджер для JS приложений. Он может работать не только в React приложениях. Он хранит состояние в дереве объектов внутри единого стора. Единственная возможность изменить состояние - отправить action. Action - это объект, который описывает действие (он отвечает на вопрос: "Что я хочу изменить в состоянии?"). Далее action попадает в reducer, где описано, как состояние должно быть изменено. (reducer отвечает на вопрос: "Как я хочу изменить стэйт?").

Как реализовать сайд эффекты в Redux

Сайд эффект - это действие, которые должно произойти на диспатчинг экшена, помимо после сохранения в стор, например, логирование в консоль или отправка запроса на сервер. Основной способ сделать сайд эффект - вызвать его в middleware. Можно написать свой middleware, а можно использовать сторонние библиотеки, например, redux thunk - для синхронных и простых асинхронных действий или redux saga - для сложных асинхронных действий. Можно вызывать сайд эффекты в action сreator'ах. Однако, это не самый лучший способ, т.к. можно задиспатчить действие и без вызова action creator, тогда сайд эффект не сработает.

React - реактивен?

Начнем с того, что React-компоненты это функции, которые мы не вызываем на прямую. Эти функции в некоторые моменты возвращают описание того что нужно рендерить. Эти функции вызывает сам React в те самые "некоторые" моменты. И React может отложить этот вызов. React рекурсивно обходит дерево компонентов и может применять оптимизации - и задерживать рендеры чтобы избежать потерю кадров. React в первую это UI фреймворк, и для того чтобы избежать тормозов такие меры оправданы. Т.к. данные могут поступать быстрее чем скорость обновления кадров - есть смысл объединять обновления в пакеты и обновлять пакетами. Поэтому React это скорее «Планировщик», и реактивность не провалятся в React в чистом виде.

Что такое синтетические события в React?

SyntheticEvent это обёртка над нативными событиями. SyntheticEvent является частью системы событий React. Ваши обработчики событий получают экземпляр SyntheticEvent, это кроссбраузерная обёртка над нативным экземпляром события. У неё такой же интерфейс, как и у нативного события, включая методы stopPropagation() и preventDefault(). Эта обёртка помогает событиям работать одинаково во всех браузерах. Еcли всё-таки нужно получить нативное браузерное событие, следует обратиться к атрибуту nativeEvent. Синтетические события отличаются от нативных событий браузера и непосредственно не связаны с ними.

Как работает браузер?

Обо всех шагах, которые совершает браузер при переходе на страницу вы можете найти в этом посте.

Задачи на написание кода

Подробный разбор одной из задач с реального собеседования вы можете найти на Boosty. Там вы можете найти как неоптимальный вариант решения, так и оптимальный. С описанием сложности каждого варианта решения в нотации Big "O" notaion. Также по теме собеседований рекомендую прочитать:

Вопросы и ответы 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 в конструкторе. Хочешь узнать больше? Еще вопросы с собеседований.