Топ 15 вопросов о React.JS на собеседовании

React.JS быстрый, с компонентной моделью и большим комьюнити, которое даст совет по любому крашу. Но на собеседовании вас спросят о другом.

1. Что делает setState?

Вызов React setState перестраивает приложение и обновляет DOM. Как это происходит? Все просто. React очень легковесный. Он строит внутри себя копию DOM дерева и при улучшении приложения он просто сравнивает предыдущую версию DOM с новой, отыскивает изменения и эффективно внедряет их в интерфейс.

С setState не нужно париться: достаточно вызвать эту функцию с новым значением в виде объекта:

this.setState({someField:someValue})

React видит точные изменения, благодаря чему предотвращает лишние манипуляции с пользовательским интерфейсом.

2. В чем разница между элементом и компонентом React.JS?

  1. Если просто: элемент – это то, что вы хотите видеть на экране.
  2. Если не так просто: элемент – объектное представление некоторого пользовательского интерфейса.

С компонентом все иначе. Это класс или функция, что может принимать данные и возвращать элементы (обычно с использованием техники создания элементов 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. Это подкреплено двумя причинами:

  1. Во-первых, повысится производительность, ведь React сможет останавливать и запускать рендеринг. И напротив, если предпочесть componentWillMount, React будет вызывать его всякий раз, как увидит в этом необходимость. Для AJAX запроса componentWillMount – не лучший вариант.
  2. Во-вторых, 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

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ

eFusion
01 марта 2020

ТОП-15 книг по JavaScript: от новичка до профессионала

В этом посте мы собрали переведённые на русский язык книги по JavaScript – ...
admin
10 июня 2018

Лайфхак: в какой последовательности изучать JavaScript

Огромный инструментарий JS и тонны материалов по нему. С чего начать? Расск...