Топ 15 вопросов о React.JS на собеседовании
React.JS быстрый, с компонентной моделью и большим комьюнити, которое даст совет по любому крашу. Но на собеседовании вас спросят о другом.
1. Что делает setState?
Вызов React setState перестраивает приложение и обновляет DOM. Как это происходит? Все просто. React очень легковесный. Он строит внутри себя копию DOM дерева и при улучшении приложения он просто сравнивает предыдущую версию DOM с новой, отыскивает изменения и эффективно внедряет их в интерфейс.
С setState не нужно париться: достаточно вызвать эту функцию с новым значением в виде объекта:
this.setState({someField:someValue})
React видит точные изменения, благодаря чему предотвращает лишние манипуляции с пользовательским интерфейсом.
2. В чем разница между элементом и компонентом React.JS?
- Если просто: элемент – это то, что вы хотите видеть на экране.
- Если не так просто: элемент – объектное представление некоторого пользовательского интерфейса.
С компонентом все иначе. Это класс или функция, что может принимать данные и возвращать элементы (обычно с использованием техники создания элементов React JSX).
3. В каких случаях Class Component лучше, чем Functional Component?
Определение компонента как класса – мощная реализация, которая необходима, если компонент имеет состояние или значимые методы. В остальных случаях можно использовать функциональный компонент: он менее мощный, но более простой.
4. Что такое refs и с чем их едят?
Предположим, нам понадобилось «достучаться» к конкретному элементу и вызвать метод. React.JS refs нужен как раз для этого. Как использовать? Добавить атрибут ref в компонент для обратного вызова. Например:
class UnControlledForm extends Component { handleSubmit = () => { console.log("Input Value: ", this.input.value) } render () { return ( <form onSubmit={this.handleSubmit}> <input type='text' ref={(input) => this.input = input} /> <button type='submit'>Submit</button> </form> ) } }
Примечательно, что поле ввода с атрибутом ref, а его значение – это функция. Она получает DOM-элемент, который вставляется в экземпляр, чтобы после получить к нему доступ в функции handleSubmit. При этом можно работать как с классом компонента, так и с функциональными компонентами, используя замыкание:
function CustomForm ({handleSubmit}) { let inputElement return ( <form onSubmit={() => handleSubmit(inputElement.value)}> <input type='text' ref={(input) => inputElement = input} /> <button type='submit'>Submit</button> </form> ) }
5. React key – это...
Настоящая палочка-выручалочка, особенно в большом коде. Ключи отслеживают измененные, добавленные или удаленные из списка элементы. Делается это так:
render () { return ( <ul> {this.state.todoItems.map(({task, uid}) => { return <li key={uid}>{task}</li> })} </ul> ) }
Важна уникальность, ведь речь идет о согласовании нового дерева с предыдущим. Ключи могут использоваться и для дочерних элементов.
6. Как бы выглядел приведенный ниже элемент Twitter в React?
<Twitter username='tylermcginnis33'> {(user) => user === null ? <Loading /> : <Badge info={user} />} </Twitter> import React, { Component, PropTypes } from 'react' import fetchUser from 'twitter' // fetchUser take in a username returns a promise // which will resolve with that username's data. class Twitter extends Component { // finish this }
В этом примере потомок компонента Twitter – функция, и чтобы решить поставленную задачу, нужно обратиться к props.children в качестве ф-ии:
import React, { Component, PropTypes } from 'react' import fetchUser from 'twitter' class Twitter extends Component { state = { user: null, } static propTypes = { username: PropTypes.string.isRequired, } componentDidMount () { fetchUser(this.props.username) .then((user) => this.setState({user})) } render () { return this.props.children(this.state.user) } }
Как писалось выше, мы обращаемся к React props children в качестве функции: вызываем ее, а затем передаем юзера.
Плюс приведенного шаблона в том, что родительский компонент отделен от дочернего. При этом «родитель» контролирует состояние, а потребитель данного компонента решает, как использовать переданные аргументы в UI.
Допустим, у нас есть другой файл, в котором мы хотим заменить Badge на Profile. Поскольку мы работаем с шаблоном render callback, то просто поменяем UI без изменения реализации родительского компонента Twitter:
<Twitter username='tylermcginnis33'> {(user) => user === null ? <Loading /> : <Profile info={user} />} </Twitter>
7. Разница между компонентами controlled и uncontrolled
Отличительной особенностью React.JS является управление компонентами и их состоянием.
Контролируемым называется такой компонент, в рамках которого React осуществляет контроль. В примере username существует в состоянии компонента, а не в DOM, и чтобы обновить username, просто вызываем setState:
class ControlledForm extends Component { state = { username: '' } updateUsername = (e) => { this.setState({ username: e.target.value, }) } handleSubmit = () => {} render () { return ( <form onSubmit={this.handleSubmit}> <input type='text' value={this.state.username} onChange={this.updateUsername} /> <button type='submit'>Submit</button> </form> ) } }
А вот к неконтролируемым относятся такие компоненты, в которых данные формы обрабатываются DOM. Для этого используется ref:
class UnControlledForm extends Component { handleSubmit = () => { console.log("Input Value: ", this.input.value) } render () { return ( <form onSubmit={this.handleSubmit}> <input type='text' ref={(input) => this.input = input} /> <button type='submit'>Submit</button> </form> ) } }
Вторые проще в реализации, ведь значения берутся из DOM с использованием refs. Только вот рекомендуется обратить внимание именно на контролируемые компоненты и разобраться в работе с ними. Дело в том, что они поддерживают быструю проверку полей, позволяют устанавливать формат входных данных и включать/отключать кнопки, а это «в стиле» React.
8. В каком моменте должны быть AJAX запросы и почему?
AJAX запросы делаются в методе componentDidMount. Это подкреплено двумя причинами:
- Во-первых, повысится производительность, ведь React сможет останавливать и запускать рендеринг. И напротив, если предпочесть componentWillMount, React будет вызывать его всякий раз, как увидит в этом необходимость. Для AJAX запроса componentWillMount – не лучший вариант.
- Во-вторых, componentDidMount гарантирует, что существует компонент для обновления. В противном случае могут посыпаться краши.
9. Что за зверь, этот shouldComponentUpdate?
О setState мы уже поговорили и выяснили, что он делает. Но что следует предпринять, дабы «защитить» некоторые компоненты от сравнения? Вот для этого и существует метод shouldComponentUpdate.
Спросите, зачем это нужно? Ну, допустим, вы точно знаете, что часть UI не изменится. И зачем нам прогонять ее через сравнение, если это не несет никакого смысла? Здесь-то и пригодится наш «зверь». Возврат значения false из метода shouldComponentUpdate позволит React понять, что включенные в метод компоненты не нуждаются в сравнении и последующих изменениях.
10. Поговорим с React.JS: режим Production
Чтобы установить NODE_ENV в production обычно используется WebPack DefinePlugin. Это позволит удалить проверку propType и другие предупреждения. Также существенно сократится код, ведь в React.JS предусмотрен Uglify, который выбрасывает «мертвый код», оставляя лишь необходимое.
11. Почему React.Children.map(props.children, () => ), а не props.children.map(() => )?
А если props.children окажется не массивом, а объектом? Пример:
<Parent> <h1>Welcome.</h1> </Parent>
Вызов props.children.map в «родителе» даст ошибку, ведь это как раз тот случай, когда props.children – объект, а не массив. React отработает, если дочерний элемент не один: их должно быть несколько. Взгляните:
<Parent> <h1>Welcome.</h1> <h2>props.children will now be an array</h2> </Parent>
Вот почему использование React.Children.map наиболее предпочтительно: с такой реализацией props.children может выступать как массивом, так и объектом.
12. Опишите обработку событий в React.JS
Кроссбраузерная совместимость – одна из основных проблем, и чтобы ее решить, обработчикам React передаются экземпляры SyntheticEvent – оболочки над нативными браузерными событиями. Данные события искусственные и обладают тем же интерфейсом, что и обычные, вот только работают они одинаково хорошо во всех браузерах.
Любопытно, что React не привязывает события к дочерним элементам. Вместо этого он слушает события верхнего уровня, что освобождает React от отслеживания слушателей при обновлении DOM и хорошо сказывается на производительности.
13. В чем разница между cloneElement и createElement?
- cloneElement предназначен для точного копирования элемента и передачи ему необходимых параметров;
- createElement – это то, что транслирует JSX, а также то, что использует React.JS для создания новых элементов, которые представляют пользовательский интерфейс.
14. Какой второй аргумент может быть передан в setState?
Это функция обратного вызова. Она реализовывается строго после setState, когда элемент отрендерен, и является полностью опциональной. Рекомендуется отдать предпочтение другому методу, нежели данной функции, но знать о ее существовании и принципе работы не помешает:
this.setState( { username: 'tylermcginnis33' }, () => console.log('setState has finished and the component has re-rendered.') )
15. Укажите на ошибку в приведенном коде
this.setState((prevState, props) => { return { streak: prevState.streak + props.count } })
Ошибок нет. Впрочем, такой вариант используется крайне редко, поэтому вызывает вопросы. Тем не менее вы можете передать в React setState функцию, которая получает параметры props и предыдущее состояние, а также возвращает новое состояние по аналогии с примерами выше. Данный вариант кода является оптимальным в том случае, если текущее состояние обновляется на основании состояния предшествующего.
Также рекомендуем Вам посмотреть:
Дайджест материалов по трудоустройству в сфере IT
Как провалить 45-минутное техническое интервью
Изучение React. С чего начать?
Подборка материалов по JavaScript