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

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

Актуальный список вопросов и ответов по ReactJS на интервью 2023 - Часть 2

1. Что такое JSX?

  • JSX — это расширение синтаксиса для JavaScript, обладающее всеми возможностями JavaScript.
  • Вы можете внедрить любое выражение JavaScript в JSX, заключив его в фигурные скобки. После компиляции выражения JSX становятся обычными объектами JavaScript.
  • Это означает, что вы можете использовать JSX внутри операторов if и циклов for, назначать его переменным, принимать в качестве аргументов и возвращать из функций.

2. Каков эквивалент следующего кода с использованием React.createElement?

const element = <h1 className="greeting">Hello, world!</h1>;
Эквивалент с использованием React.createElement будет выглядеть следующим образом:
const element = React.createElement(
  "h1",
  { className: "greeting" },
  "Hello, world!"
);

3. Что такое Redux?

  • Основная идея redux заключается в том, что все состояние приложения хранится в одном хранилище. Store (хранилище) - это просто JavaScript объект.
  • Единственный способ изменить состояние — отправить действие (action) из вашего приложения, а затем написать редьюсеры для этих действий, которые изменяют состояние.
  • Весь переход состояния хранится внутри редьюсеров и не должен иметь никаких побочных эффектов.
Подробнее о Redux можно узнать в бесплатном видео-курсе о Redux.

4. Что такое store в Redux?

Store — это JavaScript объект, который содержит состояние приложения. Наряду с этим он также имеет следующие обязанности:
  • Разрешает доступ к состоянию через getState().
  • Позволяет обновлять состояние с помощью отправки действия dispatch(action).
  • Регистрирует слушателей через subscribe(listener).
  • Обрабатывает отмену регистрации слушателей с помощью функции, возвращаемой из subscribe(listener).

5. Разница между action и reducer.

  • Action (действие) — это простые JavaScript объекты.
  • Они должны иметь тип, указывающий тип выполняемого действия.
  • По сути, действия — это некоторые данные, которые отправляются из вашего приложения в хранилище.
  • Редьюсер — это просто чистая функция, которая принимает предыдущее состояние и действие и возвращает обновленное состояние.

6. Для чего используется Redux Thunk?

  • Redux Thunk — это промежуточное программное обеспечение (middleware), которое позволяет вам писать создателей действий (action creator), которые возвращают функцию вместо действия (action). Что такое action creators?
  • Затем thunk можно использовать для задержки отправки действия, если выполняется определенное условие. Это позволяет вам обрабатывать асинхронную диспетчеризацию действий.
  • Подробнее о Redux Thunk можно узнать в полном видео-курсе о Redux Thunk.

7. Напишите кастомный хук, который можно использовать для debounce’а ввода.

// Хук useDebounce

const useDebounce = (value, delay) => {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const timeout = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(timeout);
    };
  }, [value]);

  return debouncedValue;
};

// Использование

const Counter = () => {
  const [value, setValue] = useState(0);
  const lastValue = useDebounce(value, 1000);

  return (
    <div>
      <p>
        Current Value: {value} | Debounced Value: {lastValue}
      </p>
      <button onClick={() => setValue(value + 1)}>Increment</button>
    </div>
  );
};

8. Напишите кастомный хук для копирования текста в буфер обмена.

// Хук useCopyToClipboard

function useCopyToClipboard(content) {
  const [isCopied, setIsCopied] = useState(false);

  const copy = useCallback(() => {
    navigator.clipboard
      .writeText(content)
      .then(() => setIsCopied(true))
      .then(() => setTimeout(() => setIsCopied(false), 1250))
      .catch((err) => alert(err));
  }, [content]);
  return [isCopied, copy];
}
// Использование
export default function App() {
  const [isCopied, copy] = useCopyToClipboard("Text to copy!");
  return <button onClick={copy}>{isCopied ? "Copied!" : "Copy"}</button>;
}

9. Как использовать хук useId для создания уникальных идентификаторов?

  • useId не принимает никаких параметров.
  • useId возвращает уникальную строку идентификатора, связанную с этим конкретным вызовом useId в этом конкретном компоненте.
// Использование

import { useId } from "react";

const App = () => {
  const id = useId();

  return (
    <form>
      <label htmlFor={`email-${id}`}>Email</label>
      <input type="text" id={`email-${id}`} name="email" />

      <label htmlFor={`password-${id}`}>Password</label>
      <input type="password" id={`password-${id}`} name="password" />
    </form>
  );
};

// Плохая практика - не стоит использовать в качестве key
const id = useId();

return posts.map((post) => <article key={id}>...</article>);
Подробности можно найти в статье Что за хук useId в React?.

10. Как проверить/валидировать пропсы в React?

Мы можем использовать пакет prop-types Раньше, до React v15.5, это было частью самого React.
import PropTypes from "prop-types";

function MyComponent({ name }) {
  return <div>Hello, {name}</div>;
}

MyComponent.propTypes = {
  name: PropTypes.string,
};

export default MyComponent;
Еще один вариант - это добавить к проекту TypeScript.

11. Приведите практический пример компонента высшего порядка в React.

// Компонент высшего порядка
function WithLoading(Component) {
  return function WihLoadingComponent({ isLoading, ...props }) {
    if (!isLoading) return <Component {...props} />;
    return <p>Please wait, fetching your data in no time...</p>;
  };
}
export default WithLoading;
// Использование

import UserListComponent from "./UserListComponent.js"; // импорт компонента
import WithLoading from "./withLoading.js"; // импорт HOC

const ListWithLoading = WithLoading(UserListComponent); // обернем компонент в HOC

const App = () => {
  const [loading, setLoading] = useState(true);
  const [users, setUsers] = useState([]);

  useEffect(() => {
    // запрос данных
    const dataFromApi = ["this is coming from API call", "don't show loader"];
    
    // в это время загрузчик будет показан в HOC
    // данные получены
    setUsers([...dataFromApi]);
    setLoading(false);
  }, []);

  return <ListWithLoading isLoading={loading} users={users} />;
};

12. Чем полезен хук useDeferredValue?

  • useDeferredValue — это React хук, который позволяет вам отложить обновление части пользовательского интерфейса.
  • По сути, это позволяет вам выполнять технику debounce с меньшим количеством кода.
  • Подробный разбор хука useDeferredValue можно прочитать в статье Хуки useTransition и useDeferredValue в ReactJS 18.
// Использование

import { useState, useDeferredValue } from "react";
// Компонент userList получает searchText для запроса списка пользователей
import UserList from "./UserList.js";

export default function App() {
  const [searchText, setSearchText] = useState("");
  // отправить searchText по умолчанию
  const deferredQuery = useDeferredValue(searchText);

  return (
    <>
      <label>
        Search user:
        <input
          value={searchText}
          onChange={(e) => setSearchText(e.target.value)}
        />
      </label>
      <div>
        <UserList searchText={deferredQuery} />
      </div>
    </>
  );
}

13. Как отследить клик за пределами компонента React?

export default function OutsideAlerter() {
  const clickMeDivRef = useRef(null);

  useEffect(() => {
    const handleClickOutside = (event) => {
      if (!ref?.current?.contains(event.target)) {
        alert("You clicked outside of me!");
      }
    };

    // Добавим прослушивание событий
    document.addEventListener("mousedown", handleClickOutside);

    return () => {
      // Удалим прослушивание событий
      document.removeEventListener("mousedown", handleClickOutside);
    };
  }, [clickMeDivRef]);

  return <div ref={clickMeDivRef}>Clicked me?</div>;
}

14. Почему имена компонентов React должны начинаться с заглавных букв?

В JSX имена тегов нижнего регистра считаются тегами HTML. Однако имена тегов в нижнем регистре с точкой (аксессор свойства) не являются таковыми.
  • <person /> компилируется в React.createElement('person') (тег html)
  • компилируется в React.createElement(Person)
  • <obj.person /> компилируется в React.createElement(obj.person)
// Ошибка! Это компонент и должен начинаться с заглавной буквы
function person(props) {
  // Верно! Это использование <div> верно, т.к. div это валидный элемент
  return <div>{props.isLearning ? "Great!" : "Hello!"}</div>;
}

function App() {
  // Ошибка! React считает <person /> тэгом HTML, т.к. Не с заглавной буквы
  return <person isLearning={true} />;
}

// Верно! Это компонент и должен начинаться с заглавной буквы
function Person(props) {
  // Верно! Это использование <div> верно, т.к. div это валидный элемент
  return <div>{props.isLearning ? "Great!" : "Hello!"}</div>;
}

function App() {
  // Верно! React знает, что <Person /> - это компонент, с заглавной буквы
  return <Person isLearning={true} />;
}

15. В чем разница между npx и npm?

  • npm — это менеджер пакетов, который можно использовать для установки пакетов node.js. npM - Manager.
  • npx— это инструмент для выполнения пакетов node.js. npX - Execute.
Неважно, установили ли вы этот пакет глобально или локально. npx временно установит его и запустит. npm также может запускать пакеты, если вы настроите файл package.json. Поэтому, если вы хотите быстро проверить/запустить пакет без его установки - используйте npx. create-react-app — это npm пакет, который должен запускаться только один раз в жизненном цикле проекта. Следовательно, предпочтительнее использовать npx для установки и запуска за один шаг.
> npx create-react-app my-app

16. Как установить фокус на поле ввода после монтирования компонента в UI?

import React, { useEffect, useRef } from "react";

const SearchPage = () => {
  const textInput = useRef(null);

  useEffect(() => {
    textInput.current.focus();
  }, []);

  return (
    <div>
      <input ref={textInput} type="text" />
    </div>
  );
};
Еще больше вопросов с собеседований

Паттерны ReactJS видео-курс

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

О паттернах в React проектах

Компоненты высшего порядка ReactJS (Higher-order components)

Паттерн Компонент высшего порядка назван по аналогии с функциями высшего порядка. Функция высшего порядка - это функция, которая либо принимает функцию как аргумент, либо возвращает функцию как результат. И то же самое можно сделать с компонентами. Функция (Higher Order component, HOC) может принимать компонент в качестве аргумента, что-то с ним делать и возвращать модифицированный (каким-то образом улучшенный) компонент. Смотреть на Rutube

Как использовать Компоненты высшего порядка ReactJS

Смотреть на Rutube

Паттерн Render Props в ReactJS

В этом видео поговорим о паттерне Render props в ReactJS, напишем примеры с разными кейсами, где render props полезны, посмотрим на проп children и передадим в него аргументы. Render prop - это функция, которая возвращает JSX, и эта функция используется как проп в компоненте. К пропсам с таким поведением принято добавлять префикс render (например, renderContent), чтобы отличать обычные пропсы от тех что возвращают JSX. Смотреть на Rutube

Паттерн Compound Components в React - Составные компоненты

Составные компоненты (Compound Components) в ReactJS - это такой паттерн, в котором взаимосвязанные компоненты используются вместе. Эти компоненты используют общее состояние для общения друг с другом. Сам Compound Component состоит из нескольких компонентов поменьше, которые обычно объединяют в единый namespace. В этом видео напишем компонент с использованием паттерна Compound Components. Смотреть на Rutube

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

Смотреть на Rutube