Вопросы и ответы React собеседования 2023 - Часть 2
год назад·6 мин. на чтение
Актуальный список вопросов и ответов по ReactJS на интервью 2023 - Часть 2
- Вопросы и ответы ReactJS собеседования 2023 - Часть 1
- Вопросы и ответы ReactJS собеседования 2023 - Часть 2 (эта статья)
- Вопросы и ответы ReactJS собеседования 2023 - Часть 3
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) из вашего приложения, а затем написать редьюсеры для этих действий, которые изменяют состояние.
- Весь переход состояния хранится внутри редьюсеров и не должен иметь никаких побочных эффектов.
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
в этом конкретном компоненте.
Подробности можно найти в статье Что за хук useId в React?.// Использование 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>);
10. Как проверить/валидировать пропсы в React?
Мы можем использовать пакетprop-types
Раньше, до React v15.5, это было частью самого React.
Еще один вариант - это добавить к проекту TypeScript.import PropTypes from "prop-types"; function MyComponent({ name }) { return <div>Hello, {name}</div>; } MyComponent.propTypes = { name: PropTypes.string, }; export default MyComponent;
11. Приведите практический пример компонента высшего порядка в React.
- Напишем компонент высшего порядка (HOC) для отображения загрузки, пока компонент ожидает данные.
- Больше о компонентах высшего порядка можно узнать в видео Как использовать Компоненты высшего порядка React и Паттерн Render Props в ReactJS.
// Компонент высшего порядка 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.
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> ); };
9 вопросов на собеседовании, которые должен знать Senior React разработчик
год назад·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
:
Еще один способ обработки асинхронных функций в React — использовать библиотеку, такую как axios или fetch, для выполнения вызовов API. Вот пример использования axios: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> ); }
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
с соответствующим номером страницы.
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
для создания ссылок, которые перемещаются между маршрутами в вашем приложении.
Подробнее о React Router читайте в серии статей:import { Link } from 'react-router-dom'; ... <Link to="/about">About</Link>