Топ 44 вопроса на собеседовании по React Frontend
Когда дело доходит до собеседования на должность фронтенд-разработчика React, крайне важно быть хорошо подготовленным к техническим вопросам. React стал одной из самых популярных библиотек JavaScript для создания пользовательских интерфейсов, и работодатели часто сосредотачивают внимание на оценке понимания кандидатами основных концепций React, лучших практик и связанных с ним технологий.
В этой статье мы рассмотрим полный список вопросов, которые обычно задают на собеседованиях с фронтенд-разработчиками React. Ознакомившись с этими вопросами и ответами на них, вы сможете повысить свои шансы на успех и продемонстрировать свои навыки разработки React. Итак, давайте углубимся и рассмотрим ключевые темы, которые вы должны быть готовы рассмотреть на собеседовании с React Frontend Developer.
1. Какие хуки React вы знаете?
useState
: используется для управления состоянием функциональных компонентов.useEffect
: используется для выполнения побочных эффектов в функциональных компонентах, таких как получение данных или подписка на события.useContext
: используется для доступа к значению контекста React внутри функционального компонента.useRef
: используется для создания изменяемых ссылок на элементы или значения, которые сохраняются при рендеринге.useCallback
: используется для запоминания функций во избежание ненужного повторного рендеринга.useMemo
: используется для запоминания значений с целью повышения производительности за счет кэширования дорогостоящих вычислений.useReducer
: используется для управления состоянием с помощью функции редуктора, аналогично тому, как работает Redux.useLayoutEffect
: аналогично useEffect, но эффект выполняется синхронно после всех мутаций DOM.
Эти хуки предоставляют мощные инструменты для управления состоянием, обработки побочных эффектов и повторного использования логики в функциональных компонентах React.
2. Что такое виртуальный DOM?
Virtual DOM — это концепция React, при которой создается и хранится в памяти облегченное виртуальное представление фактического DOM (объектная модель документа). Это метод программирования, используемый для оптимизации производительности веб-приложений.
Когда в данные или состояние компонента React вносятся изменения, виртуальный DOM обновляется вместо прямого манипулирования реальным DOM. Затем виртуальный DOM вычисляет разницу между предыдущим и обновленным состоянием компонента, известную как процесс «различия».
Как только различия выявлены, React эффективно обновляет только необходимые части реального DOM, чтобы отразить изменения. Такой подход сводит к минимуму количество фактических манипуляций с DOM и повышает общую производительность приложения.
Используя виртуальный DOM, React позволяет создавать динамические и интерактивные пользовательские интерфейсы, обеспечивая при этом оптимальную эффективность и скорость рендеринга.
3. Как визуализировать массив элементов?
Чтобы визуализировать массив элементов, вы можете использовать map()
метод для перебора массива и возврата нового массива элементов React.
const languages = [ "JavaScript", "TypeScript", "Python", ]; function App() { return ( <div> <ul>{languages.map((language) => <li>{language}</li>)}</ul> </div> ); }
4. В чем разница между контролируемыми и неконтролируемыми компонентами?
Разница между управляемыми и неуправляемыми компонентами заключается в том, как они управляют и обновляют свое состояние .
Контролируемые компоненты — это компоненты, состояние которых контролируется React.
Компонент получает свое текущее значение и обновляет его через свойства. Он также запускает функцию обратного вызова при изменении значения. Это означает, что компонент не хранит свое внутреннее состояние. Вместо этого родительский компонент управляет и передает значение контролируемому компоненту.
import { useState } from 'react'; function App() { const [value, setValue] = useState(''); return ( <div> <h3>Controlled Component</h3> <input name="name" value={name} onChange={(e) => setValue(e.target.value)} /> <button onClick={() => console.log(value)}>Get Value</button> </div> ); }
С другой стороны, неконтролируемые компоненты управляют своим собственным состоянием внутри, используя ссылки или другие методы. Они хранят и обновляют свое состояние независимо, не полагаясь на props или обратные вызовы. Родительский компонент имеет меньший контроль над состоянием неконтролируемых компонентов.
import { useRef } from 'react'; function App() { const inputRef = useRef(null); return ( <div className="App"> <h3>Uncontrolled Component</h3> <input type="text" name="name" ref={inputRef} /> <button onClick={() => console.log(inputRef.current.value)}>Get Value</button> </div> ); }
5. В чем разница между компонентами React на основе классов и функциональными?
Основное различие между компонентами на основе классов и функциональными компонентами заключается в том, как они определяются и какой синтаксис они используют.
Компоненты на основе классов определяются как классы ES6 и расширяют React.Component
класс. Они используют этот render
метод для возврата JSX (JavaScript XML), который определяет выходные данные компонента. Компоненты класса имеют доступ к методам жизненного цикла компонента и управлению состоянием через this.state
и this.setState()
.
class App extends React.Component { state = { value: 0, }; handleAgeChange = () => { this.setState({ value: this.state.value + 1 }); }; render() { return ( <> <p>Value is {this.state.value}</p> <button onClick={this.handleAgeChange}> Increment value </button> </> ); } }
С другой стороны, функциональные компоненты определяются как простые функции JavaScript. Они принимают props в качестве аргументов и напрямую возвращают JSX.
Функциональные компоненты не имеют доступа к методам или состоянию жизненного цикла. Однако с появлением React Hooks в React 16.8 функциональные компоненты теперь могут управлять состоянием и использовать другие функции, такие как контекст и эффекты.
import { useState } from 'react'; const App = () => { const [value, setValue] = useState(0); const handleAgeChange = () => { setValue(value + 1); }; return ( <> <p>Value is {value}</p> <button onClick={handleAgeChange}> Increment value </button> </> ); }
В целом функциональные компоненты считаются более простыми для чтения и тестирования. Рекомендуется использовать функциональные компоненты везде, где это возможно, если нет особой необходимости в компонентах на основе классов.
6. Каковы методы жизненного цикла компонента?
Методы жизненного цикла — это способ подключиться к различным этапам жизненного цикла компонента, позволяя выполнять определенный код в определенное время.
Вот список основных методов жизненного цикла:
constructor
: это первый метод, вызываемый при создании компонента. Он используется для инициализации обработчиков событий состояния и привязки. В функциональных компонентах вы можете использоватьuseState
хук для аналогичных целей.render
: этот метод отвечает за отрисовку разметки JSX и возвращает содержимое, отображаемое на экране.componentDidMount
: этот метод вызывается сразу после визуализации компонента в DOM. Он обычно используется для задач инициализации, таких как вызовы API или настройка прослушивателей событий.componentDidUpdate
: этот метод вызывается при изменении свойств или состояния компонента. Это позволяет вам выполнять побочные эффекты, обновлять компонент на основе изменений или запускать дополнительные вызовы API.componentWillUnmount
: этот метод вызывается непосредственно перед удалением компонента из DOM. Он используется для очистки любых ресурсов, настроенных вcomponentDidMount
, например, для удаления прослушивателей событий или отмены таймеров.
Некоторые методы жизненного цикла, такие как componentWillMount
, componentWillReceiveProps
и componentWillUpdate
, устарели или заменены альтернативными методами или перехватчиками.
Что касается «это», то оно относится к текущему экземпляру компонента класса. Это позволяет вам получить доступ к свойствам и методам внутри компонента. В функциональных компонентах «this» не используется, поскольку функции не привязаны к конкретному экземпляру.
7. Каковы особенности использования useState?
useState
возвращает значение состояния и функцию для его обновления.
const [value, setValue] = useState('Some state');
Во время первоначального рендеринга возвращаемое состояние соответствует значению, переданному в качестве первого аргумента. Функция setState
используется для обновления состояния. Он принимает новое значение состояния в качестве параметра и ставит в очередь повторный рендеринг компонента . Функция setState
также может принимать в качестве параметра функцию обратного вызова, которая принимает в качестве параметра предыдущее значение состояния.
8. Каковы особенности использования useEffect?
Хук useEffect
позволяет выполнять побочные эффекты в функциональном компоненте.
Мутации, подписки, таймеры, ведение журналов и другие побочные эффекты не допускаются внутри основной части функционального компонента, известного как этап рендеринга React. Это может привести к запутанным ошибкам и несоответствиям в пользовательском интерфейсе.
Вместо этого рекомендуется использовать useEffect. Функция, переданная в useEffect, будет выполняться после того, как рендеринг будет зафиксирован на экране, или если вы передадите массив зависимостей в качестве второго параметра, функция будет вызываться каждый раз, когда одна из зависимостей изменится.
useEffect(() => { console.log('Logging something'); }, [])
9. Как отследить отмонтирование функционального компонента?
Часто useEffect
создавайте ресурсы, которые необходимо очистить или сбросить, прежде чем компонент покинет экран, например подписку или идентификатор таймера.
Для этого переданная функция useEffect
может возвращать функцию очистки . Функция очистки запускается перед удалением компонента из пользовательского интерфейса, чтобы предотвратить утечки памяти. Кроме того, если компонент визуализируется несколько раз (как это обычно бывает), предыдущий эффект очищается перед выполнением следующего эффекта.
useEffect(() => { function handleChange(value) { setValue(value); } SomeAPI.doFunction(id, handleChange); return function cleanup() { SomeAPI.undoFunction(id, handleChange); }; })
10. Что такое props в React?
Props — это данные, которые передаются компоненту от родителя. Props
доступны только для чтения и не могут быть изменены.
// Parent component const Parent = () => { const data = "Hello, World!"; return ( <div> <Child data={data} /> </div> ); }; // Child component const Child = ({ data }) => { return <div>{data}</div>; };
11. Что такое менеджер состояний и с какими из них вы работали или знаете?
Менеджер состояний(Manager state) — это инструмент или библиотека, которая помогает управлять состоянием приложения. Он предоставляет централизованное хранилище или контейнер для хранения и управления данными, к которым могут обращаться и обновлять различные компоненты приложения.
Менеджер состояний решает несколько задач. Во-первых, рекомендуется отделять данные и связанную с ними логику от компонентов. Во-вторых, при использовании локального состояния и передаче его между компонентами код может стать запутанным из-за возможности глубокой вложенности компонентов. Имея глобальное хранилище, мы можем получать доступ к данным из любого компонента и изменять их.
Наряду с React Context в качестве библиотек управления состоянием обычно используются Redux или MobX.
12. В каких случаях можно использовать локальное состояние, а когда следует использовать глобальное состояние?
Локальное состояние рекомендуется использовать в тех случаях, когда оно используется только внутри одного компонента и нет планов передавать его другим компонентам. Локальное состояние также используется в компоненте, представляющем отдельный элемент списка. Однако если декомпозиция компонентов включает в себя вложенные компоненты, данные которых передаются по иерархии, лучше использовать глобальное состояние.
13. Что такое редюсер в Redux и какие параметры он принимает?
Редюсер — это чистая функция, которая принимает состояние и действие в качестве параметров. Внутри редуктора мы отслеживаем тип полученного действия и в зависимости от него модифицируем состояние и возвращаем новый объект состояния.
export default function appReducer(state = initialState, action) { // The reducer normally looks at the action type field to decide what happens switch (action.type) { // Do something here based on the different types of actions default: // If this reducer doesn't recognize the action type, or doesn't // care about this specific action, return the existing state unchanged return state } }
14. Что такое действие и как изменить состояние в Redux?
Действие — это простой объект JavaScript, который должен иметь поле с
типом.
{ type: "SOME_TYPE" }
Вы также можете добавить некоторые данные в качестве полезной нагрузки . Для того
, чтобы изменить состояние необходимо вызвать функцию диспетчеризации, которой мы передаем действие
{ type: "SOME_TYPE", payload: "Any payload", }
15. Какой шаблон реализует Redux?
Redux реализует паттерн Flux , который представляет собой предсказуемый паттерн управления состоянием приложений. Это помогает управлять состоянием приложения за счет введения однонаправленного потока данных и централизованного хранилища состояния приложения.
16. Какой шаблон реализует Mobx?
Mobx реализует шаблон Observer , также известный как шаблон публикации-подписки.
17. Каковы особенности работы с Mobx?
Mobx предоставляет декораторы, такие как observable
и computed
для определения наблюдаемого состояния и реактивных функций. Действия, украшенные action, используются для изменения состояния, обеспечивая отслеживание всех изменений. Mobx также предлагает автоматическое отслеживание зависимостей, различные типы реакций, детальный контроль над реактивностью и бесшовную интеграцию с React через пакет mobx-react.
В целом, Mobx упрощает управление состоянием, автоматизируя процесс обновления на основе изменений наблюдаемого состояния.
18. Как получить доступ к переменной в состоянии Mobx?
Вы можете получить доступ к переменной в состоянии, используя observable
декоратор, чтобы определить переменную как наблюдаемую. Вот пример:
import { observable, computed } from 'mobx'; class MyStore { @observable myVariable = 'Hello Mobx'; @computed get capitalizedVariable() { return this.myVariable.toUpperCase(); } } const store = new MyStore(); console.log(store.capitalizedVariable); // Output: HELLO MOBX store.myVariable = 'Hi Mobx'; console.log(store.capitalizedVariable); // Output: HI MOBX
В этом примере объект myVariable
определяется как наблюдаемая с помощью observable
декоратора. Затем вы можете получить доступ к переменной, используя store.myVariable
. Любые изменения, внесенные в, myVariable
автоматически запускают обновления в зависимых компонентах или реакциях.
19. В чем разница между Redux и Mobx?
Redux — это более простая и продуманная библиотека управления состоянием, которая следует строгому однонаправленному потоку данных и обеспечивает неизменность. Он требует большего количества шаблонного кода и явных обновлений, но имеет отличную интеграцию с React.
Mobx, с другой стороны, предоставляет более гибкий и интуитивно понятный API с меньшим количеством шаблонного кода. Он позволяет напрямую изменять состояние и автоматически отслеживает изменения для повышения производительности. Выбор между Redux и Mobx зависит от ваших конкретных потребностей и предпочтений.
20. Что такое JSX?
По умолчанию для создания элементов в реакции используется следующий синтаксис.
const someElement = React.createElement( 'h3', {className: 'title__value'}, 'Some Title Value' );
Но мы привыкли видеть это именно так
const someElement = ( <h3 className='title__value'>Some Title Value</h3> );
Именно такая разметка и называется jsx. Это своего рода расширение языка
, упрощающее восприятие кода и разработку.
21. Что такое props drilling?
Driling props — это процесс прохождения props через несколько уровней вложенных компонентов, даже если некоторые промежуточные компоненты не используют эти props напрямую. Это может привести к созданию сложной и громоздкой структуры кода.
// Parent component const Parent = () => { const data = "Hello, World!"; return ( <div> <ChildA data={data} /> </div> ); }; // Intermediate ChildA component const ChildA = ({ data }) => { return ( <div> <ChildB data={data} /> </div> ); }; // Leaf ChildB component const ChildB = ({ data }) => { return <div>{data}</div>; };
В этом примере data
свойство передается из компонента Parent в ChildA, а затем из ChildA в ChildB, даже если ChildA не использует это свойство напрямую. Это может стать проблематичным, если существует много уровней вложенности или когда к данным должен быть доступ компонентам, расположенным ниже по дереву компонентов. Это может затруднить поддержку и понимание кода.
Детализация props может быть уменьшена за счет использования других шаблонов, таких как библиотеки управления контекстом или состоянием, такие как Redux или MobX. Эти подходы позволяют компонентам получать доступ к данным без необходимости передавать props через каждый промежуточный компонент.
22. Как отрисовать элемент условно?
Вы можете использовать любые условные операторы, включая троичные.
return ( <div> {isVisible && <span>I'm visible!</span>} </div> ); return ( <div> {isOnline ? <span>I'm online!</span> : <span>I'm offline</span>} </div> );
if (isOnline) { element = <span>I'm online!</span>; } else { element = <span>I'm offline</span>; } return ( <div> {element} </div> );
23. Для чего используется useMemo и как он работает?
useMemo
используется для кэширования и запоминания результатов вычислений.
Передайте создающую функцию и массив зависимостей. useMemo
будет пересчитывать запомненное значение только тогда, когда значение любой из зависимостей изменилось. Такая оптимизация помогает избежать дорогостоящих вычислений при каждом рендеринге.
С первым параметром функция принимает обратный вызов, в котором выполняются вычисления, а со вторым — массив зависимостей, функция будет повторно выполнять вычисления только при изменении хотя бы одной из зависимостей.
const memoValue = useMemo(() => computeFunc(paramA, paramB), [paramA, paramB]);
24. Для чего используется useCallback и как он работает?
Хук useCallback
вернет запомненную версию обратного вызова, которая изменится только в том случае, если изменяются значения одной из зависимостей.
Это полезно при передаче обратных вызовов оптимизированным дочерним компонентам, которые полагаются на равенство ссылок, чтобы предотвратить ненужный рендеринг.
const callbackValue = useCallback(() => computeFunc(paramA, paramB), [paramA, paramB]);
25. В чем разница между useMemo и useCallback?
useMemo
используется для запоминания результата вычисления, а такжеuseCallback
для запоминания самой функции.useMemo
кэширует вычисленное значение и возвращает его при последующих рендерингах, если зависимости не изменились.useCallback
кэширует саму функцию и возвращает тот же экземпляр, если зависимости не изменились.
26. Что такое контекст React?
React Context — это функция, которая позволяет передавать данные через дерево компонентов без ручной передачи props на каждом уровне. Это позволяет вам создать глобальное состояние, к которому может получить доступ любой компонент в дереве, независимо от его положения. Контекст полезен, когда вам нужно обмениваться данными между несколькими компонентами, которые не связаны напрямую через props.
React Context API состоит из трех основных частей:
createContext
: Эта функция используется для создания нового объекта контекста.Context.Provider
: этот компонент используется для предоставления значения контексту. Он оборачивает компоненты, которым требуется доступ к значению.Context.Consumer
илиuseContext
крючок: этот компонент или крючок используется для получения значения из контекста. Его можно использовать в любом компоненте провайдера контекста.
Используя React Context, вы можете избежать детализации свойств (прохождения props через несколько уровней компонентов) и легко управлять состоянием на более высоком уровне, делая ваш код более организованным и эффективным.
27. Для чего используется useContext и как он работает?
В типичном приложении React данные передаются сверху вниз (от родительского компонента к дочернему) с использованием props. Однако такой метод использования может оказаться слишком громоздким для некоторых типов props (например, выбранного языка, темы пользовательского интерфейса), которые необходимо передавать многим компонентам в приложении. Контекст предоставляет возможность совместного использования таких данных между компонентами без необходимости явно передавать props через
каждый уровень дерева.
Компонент, вызывающий useContext, всегда будет перерисовываться при
изменении значения контекста. Если повторный рендеринг компонента обходится дорого, его можно оптимизировать с помощью мемоизации.
const App = () => { const theme = useContext(ThemeContext); return ( <div style={{ color: theme.palette.primary.main }}> Some div </div> ); }
28. Для чего используется useRef и как он работает?
useRef
возвращает модифицируемый объект ссылки, свойство. Текущий из которых инициализируется переданным аргументом. Возвращенный объект будет сохраняться в течение всего времени существования компонента и не будет меняться от рендеринга к рендерингу.
Обычный вариант использования — доступ к потомку в императивном
стиле. Т.е. используя ref, мы можем явно ссылаться на элемент DOM.
const App = () => { const inputRef = useRef(null); const buttonClick = () => { inputRef.current.focus(); } return ( <> <input ref={inputRef} type="text" /> <button onClick={buttonClick}>Focus on input tag</button> </> ) }
29. Что такое React.memo()?
React.memo()
является компонентом более высокого порядка. Если ваш компонент всегда отображает одно и то же с неизменяемыми свойствами, вы можете в React.memo()
некоторых случаях обернуть его в вызов, чтобы повысить производительность, тем самым запоминая результат. Это означает, что React будет использовать результат последнего рендеринга, избегая повторного рендеринга. React.memo()
влияет только на изменения props. Если функциональный компонент обернут в React.memo и использует useState, useReducer или useContext, он будет перерисован при изменении состояния или контекста.
import { memo } from 'react'; const MemoComponent = memo(MemoComponent = (props) => { // ... });
30. Что такое React Fragment?
Возврат нескольких элементов из компонента — обычная практика в React. Фрагменты позволяют формировать список дочерних элементов без создания ненужных узлов в DOM.
<> <OneChild /> <AnotherChild /> </> // or <React.Fragment> <OneChild /> <AnotherChild /> </React.Fragment>
31. Что такое согласование React?
Согласование — это алгоритм React, используемый для отличия одного дерева элементов от другого, чтобы определить части, которые необходимо будет заменить.
Согласование — это алгоритм, лежащий в основе того, что мы называли Virtual DOM.
Определение звучит примерно так: когда вы визуализируете приложение React, дерево элементов, описывающее приложение, генерируется в зарезервированной памяти. Это дерево затем включается в среду рендеринга — например, в браузерное приложение, оно транслируется в набор операций DOM. Когда состояние приложения обновляется, создается новое дерево. Новое дерево сравнивается с предыдущим, чтобы просчитать и включить именно те операции, которые нужны для перерисовки обновленного приложения.
32. Зачем нам нужны ключи в списках при использовании map()?
Ключи помогают React определить, какие элементы были изменены, добавлены или удалены. Их необходимо указать, чтобы React мог сопоставлять элементы массива с течением времени.
Лучший способ выбрать ключ — использовать строку, которая будет четко отличать элемент списка от его соседей. Чаще всего в качестве ключей вы будете использовать идентификаторы из своих данных.
const languages = [ { id: 1, lang: "JavaScript", }, { id: 2, lang: "TypeScript", }, { id: 3, lang: "Python", }, ]; const App = () => { return ( <div> <ul>{languages.map((language) => ( <li key={`${language.id}_${language.lang}`}>{language.lang}</li> ))} </ul> </div> ); }
33. Как обрабатывать асинхронные действия в Redux Thunk?
Чтобы использовать Redux Thunk, вам необходимо импортировать его как промежуточное программное обеспечение. Создатели действий должны возвращать не просто объект, а функцию, которая принимает отправку в качестве параметра.
export const addUser = ({ firstName, lastName }) => { return dispatch => { dispatch(addUserStart()); } axios.post('https://jsonplaceholder.typicode.com/users', { firstName, lastName, completed: false }) .then(res => { dispatch(addUserSuccess(res.data)); }) .catch(error => { dispatch(addUserError(error.message)); }) }
34. Как отследить изменения поля объекта функционального компонента?
Для этого вам нужно использовать useEffect
хук и передать поле объекта как массив зависимостей.
useEffect(() => { console.log('Changed!') }, [obj.someField])
35. Как получить доступ к элементу DOM?
Ссылки создаются с помощью крючка React.createRef()
или useRef()
и прикрепляются к элементам React через атрибут ref. Получив доступ к созданной ссылке, мы можем получить доступ к элементу DOM, используя ref.current
.
const App = () => { const myRef = useRef(null); const handleClick = () => { console.log(myRef.current); // Accessing the DOM element }; return ( <div> <input type="text" ref={myRef} /> <button onClick={handleClick}>Click Me</button> </div> ); } export default App;
36. Что такое индивидуальный крючок?
Пользовательский хук — это функция, которая позволяет повторно использовать логику между различными компонентами. Это способ инкапсулировать повторно используемую логику, чтобы ее можно было легко совместно использовать и повторно использовать в нескольких компонентах. Пользовательские перехватчики — это функции, которые обычно начинаются со слова * use* и при необходимости могут вызывать другие перехватчики.
37. Что такое публичный API?
В контексте индексных файлов общедоступный API обычно относится к интерфейсу или функциям, которые предоставляются и доступны внешним модулям или компонентам.
Вот пример кода индексного файла, представляющего общедоступный API:
// index.js export function greet(name) { return `Hello, ${name}!`; } export function calculateSum(a, b) { return a + b; }
В этом примере файл index.js действует как общедоступный API, где функции greet()
и calculateSum()
экспортируются, и к ним можно получить доступ из других модулей, импортировав их. Другие модули могут импортировать и использовать эти функции как часть своей реализации:
// main.js import { greet, calculateSum } from './index.js'; console.log(greet('John')); // Hello, John! console.log(calculateSum(5, 3)); // 8
Экспортируя определенные функции из индексного файла, мы определяем общедоступный API модуля, позволяя другим модулям использовать эти функции.
38. Каковы правила создания собственного крючка?
- Имя хука начинается со слова «use».
- При необходимости используйте существующие крючки.
- Не вызывайте хуки условно.
- Извлеките повторно используемую логику в собственный хук.
- Пользовательские хуки должны быть чистыми функциями.
- Пользовательские перехватчики могут возвращать значения или другие перехватчики.
- Назовите пользовательский крючок описательно.
39. Что такое SSR (серверный рендеринг)?
Серверный рендеринг (SSR) — это метод, используемый для рендеринга страниц на сервере и отправки полностью визуализированной страницы клиенту для отображения. Он позволяет серверу генерировать полную HTML-разметку веб-страницы, включая ее динамическое содержимое, и отправлять ее клиенту в качестве ответа на запрос.
При традиционном подходе к рендерингу на стороне клиента клиент получает минимальную HTML-страницу, а затем отправляет серверу дополнительные запросы на данные и ресурсы, которые используются для рендеринга страницы на стороне клиента. Это может привести к замедлению начальной загрузки страницы и отрицательно повлиять на поисковую оптимизацию (SEO), поскольку сканерам поисковых систем трудно индексировать контент, основанный на JavaScript.
При использовании SSR сервер заботится о рендеринге веб-страницы, выполняя необходимый код JavaScript для создания окончательного HTML-кода. Это означает, что клиент получает полностью визуализированную страницу с сервера, что снижает потребность в дополнительных запросах ресурсов. SSR сокращает время начальной загрузки страницы и позволяет поисковым системам легко индексировать контент, что приводит к улучшению SEO.
SSR обычно используется в фреймворках и библиотеках, таких как Next.js для React и Nuxt.js для Vue.js, чтобы обеспечить возможности рендеринга на стороне сервера. Эти платформы обрабатывают логику рендеринга на стороне сервера, что упрощает реализацию SSR.
40. Каковы преимущества использования реформы в сфере безопасности?
- Уменьшение времени начальной загрузки : SSR позволяет серверу отправлять клиенту полностью визуализированную HTML-страницу, уменьшая объем обработки, необходимой на стороне клиента. Это сокращает время начальной загрузки, поскольку пользователь быстрее видит всю страницу.
- SEO-дружественность : поисковые системы могут эффективно сканировать и индексировать содержимое SSR-страниц, поскольку в первоначальном ответе доступен полностью визуализированный HTML-код. Это улучшает видимость в поисковых системах и помогает улучшить рейтинг в поисковых системах.
- Доступность : SSR гарантирует, что контент доступен пользователям, у которых отключен JavaScript или которые используют вспомогательные технологии. Генерируя HTML на сервере, SSR обеспечивает надежный и доступный интерфейс для всех пользователей.
- Производительность в средах с низкой пропускной способностью : SSR уменьшает объем данных, необходимых для загрузки клиентом, что делает его выгодным для пользователей в средах с низкой пропускной способностью или высокой задержкой. Это особенно важно для мобильных пользователей или пользователей с медленным подключением к Интернету.
Хотя SSR предлагает эти преимущества, важно отметить, что он может привести к большей нагрузке на сервер и сложности обслуживания по сравнению с методами рендеринга на стороне клиента. Особое внимание следует уделить таким факторам, как кэширование, масштабируемость и оптимизация производительности рендеринга на стороне сервера.
41. Какие основные функции Next.js вы знаете?
getStaticProps
: этот метод используется для получения данных во время сборки и предварительной визуализации страницы как статического HTML. Это гарантирует, что данные доступны во время сборки и не изменяются при последующих запросах.
export async function getStaticProps() { const res = await fetch('https://api.example.com/data'); const data = await res.json(); return { props: { data } }; }
getServerSideProps
: этот метод используется для получения данных по каждому запросу и предварительной обработки страницы на сервере. Его можно использовать, когда вам нужно получить данные, которые могут часто меняться или зависят от пользователя.
export async function getServerSideProps() { const res = await fetch('https://api.example.com/data'); const data = await res.json(); return { props: { data } }; }
getStaticPaths
: этот метод используется в динамических маршрутах для указания списка путей, которые должны быть предварительно отображены во время сборки. Обычно он используется для получения данных для динамических маршрутов с параметрами.
export async function getStaticPaths() { const res = await fetch('https://api.example.com/posts'); const posts = await res.json(); const paths = posts.map((post) => ({ params: { id: post.id } })); return { paths, fallback: false }; }
42. Что такое линтеры?
Линтеры — это инструменты, используемые для проверки исходного кода на наличие потенциальных ошибок, ошибок, стилистических несоответствий и проблем с удобством сопровождения. Они помогают обеспечить соблюдение стандартов кодирования и обеспечить качество и согласованность кода во всей кодовой базе.
Линтеры работают, сканируя исходный код и сравнивая его с набором предопределенных правил или рекомендаций. Эти правила могут включать соглашения о синтаксисе и форматировании, лучшие практики, потенциальные ошибки и запахи кода. Когда линтер обнаруживает нарушение правила, он генерирует предупреждение или ошибку, выделяя конкретную строку или строки кода, требующие внимания.
Использование линтера может дать несколько преимуществ:
- Качество кода . Линтеры помогают выявлять и предотвращать потенциальные ошибки, запахи кода и анти-шаблоны, что приводит к повышению качества кода.
- Согласованность : линтеры обеспечивают соблюдение соглашений по кодированию и рекомендаций по стилю, обеспечивая единообразие форматирования и структуры кода во всей кодовой базе, даже когда над одним проектом работают несколько разработчиков.
- Удобство сопровождения . Выявляя проблемы на ранней стадии и продвигая передовые методы кодирования, линтеры способствуют удобству сопровождения кода, упрощая понимание, изменение и расширение базы кода.
- Эффективность : Линтеры могут сэкономить время разработчиков, автоматизируя процессы проверки кода и выявляя типичные ошибки до того, как они смогут вызвать проблемы во время разработки или производства.
Некоторые популярные линтеры — это ESLint для JavaScript и Stylelint для CSS и Sass.
43. Какие архитектурные решения для React вы знаете?
Существует несколько архитектурных решений и шаблонов для создания проектов React. Некоторые популярные из них включают в себя:
- MVC (Модель-Представление-Контроллер) : MVC — это традиционный архитектурный шаблон, который разделяет приложение на три основных компонента — Модель, Представление и Контроллер. React можно использовать на уровне представления для рендеринга пользовательского интерфейса, а другие библиотеки или платформы можно использовать для слоев модели и контроллера.
- Flux : Flux — это архитектура приложений, представленная Facebook специально для приложений React. Он следует за однонаправленным потоком данных, где данные передаются в одном направлении, что упрощает понимание и отладку изменений состояния приложения.
- Атомный дизайн : атомарный дизайн не является специфичным для React, но представляет собой методологию проектирования, которая делит пользовательский интерфейс на более мелкие, повторно используемые компоненты. Он поощряет создание небольших, автономных компонентов, которые можно скомпоновать для создания более сложных пользовательских интерфейсов.
- Шаблон «Контейнер и компонент» . Этот шаблон отделяет представление (Компонент) от логики и управления состоянием (Контейнер). Компоненты отвечают за отображение пользовательского интерфейса, а контейнеры — за бизнес-логику и управление состоянием.
- Feature-Sliced Design : это современный архитектурный подход, используемый для организации и структурирования приложений React. Он направлен на решение проблем масштабируемости, удобства обслуживания и повторного использования путем разделения кодовой базы приложения на основе функций или модулей.
44. Что такое функциональный дизайн?
Это современный архитектурный подход, используемый для организации и структурирования приложений React. Он направлен на решение проблем масштабируемости, удобства обслуживания и повторного использования путем разделения кодовой базы приложения на основе функций или модулей.
В Feature-Sliced Design каждая функция или модуль приложения организованы в отдельный каталог, содержащий все необходимые компоненты, действия, редукторы и другие связанные файлы. Это помогает сохранить модульность и изоляцию кодовой базы, что упрощает разработку, тестирование и поддержку.
Функциональный дизайн способствует четкому разделению задач и инкапсулирует функциональность в отдельные функции. Это позволяет разным командам или разработчикам независимо работать над разными функциями, не беспокоясь о конфликтах или зависимостях.