Вопросы по React на собеседовании
2 года назад·3 мин. на чтение
В этой статье рассмотрим вопросы, которые могут встретиться на собеседовании по ReactJS на позицию React или frontend разработчика в 2023 году.
Что нового появилось в React 18?
1. Автоматический батчинг setState
В React 17 только React события будут обрабатываться пакетно, а нативные JavaScript события, промисы, setTimeout и setInterval обрабатываться не будут. В React 18 все события обрабатываются пакетно, т.е. несколько setState будут объединены в одно выполнение, что повышает производительность. На уровне данных несколько обновлений состояния объединяются в одну обработку (на уровне представления несколько визуализаций объединяются в одну визуализацию).2. Новый root API
В React 18 представлен новый root API, который поддерживает новый конкурентный рендеринг.// React 17 import React from "react" import ReactDOM from "react-dom" import App from "./App" const root = document.getElementById("root") ReactDOM.render(root, <App />) // unmount the component ReactDOM.unmountComponentAtNode(root) // React 18 import React from "react" import ReactDOM from "react-dom/client" import App from "./App" const root = document.getElementById("root") ReactDOM.createRoot(root).render(<App />) // unmount the component root.unmount()
3. Прекращение поддержки IE
Удалена поддержка браузера IE. Все новые функции, представленные React 18, основаны на современных браузерах. Если вам нужна поддержка IE, вам нужно вернуться к версии React 17.4. flushSync
Используется, чтобы заставить React сбросить всю ожидающую работу и синхронно обновить DOM.import React, {useState} from "react" import {flushSync} from "react-dom" const App = () => { const [count, setCount] = useState(0) const [count2, setCount2] = useState(0) return ( <div className="App"> <button onClick={() => { // первое обновление flushSync(() => { setCount(count => count + 1) }) // второе обновление flushSync(() => { setCount2(count2 => count2 + 1) }) }}>click</ button > <span>count: {count}</ span > <span>count2: {count2}</ span > </div> ) } export default App
5. Возвращаемое значение React компонента
В React 17 для возврата пустого компонента можно использовать только null, а явное возвращение undefined вызовет ошибку. В React 18 поддерживается возвратnull
и undefined
.
6. Поддержка useId
Генерирует один и тот же уникальный идентификатор на сервере и клиенте, чтобы избежать несовместимости при гидратации.
7. Concurrent mode (Конкурентный режим)
Конкурентный режим — это не фича, а архитектура. Это помогает приложениям оставаться отзывчивыми, подстраиваясь под производительность устройства пользователя и скорость сети, а также устраняет блокировку механизмов рендеринга, делая рендеринг прерываемым. В React несколько состояний могут быть обновлены одновременно. Разница в том, чтобы синхронные непрерываемые обновления стали асинхронными прерываемыми обновлениями.useDeferredValue
и startTransition
используются для обозначения несрочного обновления.
Почему React компоненты не могут возвращать несколько элементов?
Почему компоненты React могут иметь только один корневой элемент?- Компонент React в конце будет скомпилирован в функцию рендеринга, и возвращаемое значение функции может быть только одно. Если он не обернут в отдельный корневой узел, несколько значений будут возвращаться параллельно, что не допускается в JavaScript.
class App extends React.Component{ render() { return( <div> <h1 className="title">Hello</h1> <span>World</span> </div> ) } // После компиляции class App extends React.Component { render() { return React.createElement('div', null, [ React.createElement('h1', {className:'title'}, 'Hello'), React.createElement('span', null, 'World') ] ) } }
- Виртуальный DOM React представляет собой древовидную структуру, и корневой узел дерева может быть только один. При наличии нескольких корневых узлов невозможно подтвердить, какое дерево нужно обновить.
Как компоненты React могут возвращать несколько компонентов?
- Используя HOC (Higher Order Functions)
- Используя
React.Fragment
, вы можете добавить список элементов в группу, не создавая дополнительных узлов.
renderList() { list.map((item, key) => { return ( <React.Fragment> <tr key={item.id}> <td>{item.name}</td> <td>{item.age}</td> <td>{item.address}</td> </tr> </React.Fragment> ) }) }
- Используя массив
renderList(){ list.map((item, key) => { return [ <tr key={item.id}> <td>{item.name}</td> <td>{item.age}</td> <td>{item.address}</td> </tr> ] }) }
Каковы способы общения между React компонентами?
Существует множество способов взаимодействия компонентов, которые можно разделить на следующие категории:- Взаимодействие родительского компонента с дочерним компонентом
- Дочерний компонент взаимодействует с родительским компонентом
- Общение между соседними элементами
- Родительский компонент взаимодействует с дочерними компонентами
- Связь независимых компонентов
Что такое npm workspaces?
2 года назад·2 мин. на чтение
Набор функций в npm cli, с помощью которого можно управлять несколькими пакетами из единого корня проекта.
Workspaces (рабочие области) — это набору функций в npm cli, с помощью которого можно управлять несколькими пакетами из единого корневого пакета верхнего уровня. Этот функционал появился с 7й версии.
Workspaces упрощают работу с монорепозиториями. Монорепозиторий - это способ организации проекта в котором множество подпроектов хранится в одном и том же репозитории.
Workspaces упрощает работу со связанными пакетами. В нем автоматизирован процесс связывания (linking) и нет необходимости вручную использовать
npm link
для добавления ссылок на пакеты, которые должны быть связаны символическими ссылками в текущую папку node_modules
. Каждый отдельный workspaces - это отдельный изолированный модуль, пакет или подпроект.
Создание проекта и workspace’ов
Проинициализируем проект, запустивnpm init
. Далее добавим в package.json
поле workspaces
. В это поле добавляем имена workspace'ов. packages/
обозначает, что мы поместим подпроекты в папку packages
.
Создадим папки"workspaces": [ "packages/components", "packages/app" ]
packages/components
и packages/app
и запустим npm init
в каждой из них. Получаем такую структуру:
Запустимpackages/ app/ package.json components/ package.json package.json
npm install
. После запуска npm install
папки packages/components
и packages/app
будут связаны символическими ссылками с node_modules
. В результате структура папок будет выглядеть следующим образом:
packages/ app/ package.json components/ package.json node_modules/ // добавилось app/ // symlink на ../packages/app components/ // symlink на ../packages/components package.json package-lock.json // добавилось
Автоматическое создание нового workspace
Для того чтобы не создавать папки самим, можно запустить готовую команду. Добавим еще один подпроект с названиемapi
.
Эта команда автоматически:npm init -w ./packages/api
- создаст папку
api
сpackage.json
внутри; - добавит новый workspace в конфигурацию корневого
package.json
; - создаст symlink.
Добавление зависимостей в workspace
Для того чтобы добавить зависимость в определенный workspace нужно указать этот workspace в командеnpm install
:
Подобным образом можно запускать командыnpm install lodash -w components
uninstall
, ci
и т.д.
Как ссылаться на workspace и использовать его
Воспользуемся функцией из одного workspace’а в другом. Создадим небольшую функцию в пакете components:Вызовем эту функцию в пакете// packages/components/index.js module.exports = { toUpperCase: (str) => String(str).toUpperCase() }
app
:
Запустим скрипт:// packages/app/index.js const { toUpperCase } = require('components') console.log(toUpperCase('hello, world!')) // => 'HELLO, WORLD!'
node ./packages/app/index.js
Запуск команд в контексте workspace’а
Можно использовать параметрworkspace
для запуска команд в контексте выбранного пакета. Кроме того, если текущий каталог находится внутри workspace’а, конфигурация workspace’а задается неявно, а префикс устанавливается для корневого workspace’а.
Из корня проекта запустим команду start
для workspace’а app
.
Внутри workspace’а можно запустить команду обычном образом.npm run start --workspace=app
Аргументcd packages/app npm run start
--workspace
можно указать несколько раз для запуска команды для нескольких workspace’ов:
Для запуска команды в контексте всех workspace’ов нужно указать флагnpm run start --workspace=app --workspace=api
--workspaces
. Эта команда запустит команду start
для каждого workspace’а в порядке указанном в поле workspaces
в package.json
.
Однако, может оказаться, что не во всех workspace’ах будет определен вызываемый скрипт. Чтобы избежать ошибокnpm run start --workspaces
npm ERR! Error: Missing script: "start"
, нужно указать флаг --if-present
. В этом случае npm пропустит workspace’ы, в которых вызываемый скрипт не определен.
Исходный кодnpm run start --workspaces --if-present