React.js: понятное руководство для начинающих

Предостережения

Вы можете столкнуться с неочевидными проблемами, когда работаете с компонентами высшего порядка.

Не используйте HOC внутри рендер-метода

Алгоритм сравнения React (известный как согласование или reconciliation) использует тождественность компонентов чтобы определить нужно ли обновить существующее поддерево, или убрать и монтировать вместо него новое. Если компонент, полученный из , идентичен () компоненту из предыдущего рендера, то React рекурсивно продолжит сравнивать поддерево. Если компоненты не равны, React полностью удалит и заменит старое поддерево.

Обычно нас это не беспокоит

Однако, важно учитывать что мы не можем применять компоненты высшего порядка внутри рендер-метода компонента:. Проблема не только в производительности

Повторное монтирование компонента обнуляет его состояние, а также состояние его дочерних компонентов

Проблема не только в производительности. Повторное монтирование компонента обнуляет его состояние, а также состояние его дочерних компонентов.

Не применяйте HOC в определении другого компонента. Сначала нужно отдельно получить компонент из HOC, и только потом использовать его. Таким образом React будет сравнивать один и тот же компонент при повторном рендере.

При необходимости (в редких случаях) можно динамически применять HOC в методах жизненного цикла или конструкторе компонента.

Копируйте статические методы

Иногда бывает полезно определить статические методы компонента. Например, статический метод библиотеки Relay позволяет составить композицию из фрагментов данных GraphQL.

Когда мы применяем HOC, то заворачиваем оригинальный компонент в контейнер. Поэтому у нового компонента не будет статических методов оригинального компонента.

Скопируйте недостающие методы в контейнер:

К сожалению, вы должны точно знать какие методы копировать. Вы можете воспользоваться hoist-non-react-statics, чтобы автоматически скопировать не связанные с React статические методы:

Другое возможное решение — экспортировать статические методы отдельно от компонента.

Рефы не передаются

По соглашению компоненты высшего порядка передают оборачиваемому компоненту все пропсы, кроме рефов. на самом деле не проп, как, например, , и поэтому иначе обрабатывается React. Реф элемента, созданного компонентом из HOC, будет указывать на экземпляр ближайшего в иерархии контейнера, а не на оборачиваемый компонент.

Вы можете решить эту проблему с помощью API-метода (добавлен в React 16.3). Узнать подробнее в главе Перенаправление рефов.

Пропсы можно только читать

Компонент никогда не должен что-то записывать в свои пропсы — вне зависимости от того, .

Возьмём для примера функцию :

Такие функции называют «чистыми», потому что они не меняют свои входные данные и предсказуемо возвращают один и тот же результат для одинаковых аргументов.

А вот пример нечистой функции — она записывает данные в свои же аргументы:

React достаточно гибкий, но есть одно правило, которое нельзя нарушать:

React-компоненты обязаны вести себя как чистые функции по отношению к своим пропсам.

Конечно, интерфейсы приложений обычно изменяются с течением времени. В следующей главе мы узнаем о том, что такое «состояние» компонента. Состояние даёт компонентам возможность реагировать на действия пользователя, ответы сервера и другие события, не нарушая чистоту компонента.

Знакомство с Preact

Как я и сказал выше, Preact – это альтернатива React весом в 3кб, разработанная Джейсоном Миллером  и его помощниками. Preact был разработан с целью создания JavaScript фреймворка маленького размера, но предлагающего все те же функции, что и React.

Он весит всего 3кб, а это значит, что вам больше не придется волноваться о том, что ваша JavaScript библиотека/фреймворк займет много места в общем весе приложения.

Preact быстр, но не только из-за веса. Это одна из самых быстрых DOM библиотек из всех существующих благодаря простой и предсказуемой реализации diff.

Ключевые качества и цели Preact:

  • Производительность: быстрый и эффективный;
  • Размер: весит крайне мало;
  • Эффективность: эффективно использует память;
  • Понятность: разобраться в этой библиотеке можно за несколько часов;
  • Совместимость: Preact стремится к тому, чтобы быть максимально совместимым с React API. preact-compat пытается достичь максимальной совместимости. О нем мы поговорим позже.

Preact отлично работает во всех браузерах, но с IE7 и IE8, конечно же, могут возникнуть проблемы. К тому же у Preact есть большое сообщество с огромным количеством плагинов, и многие компании начинают переключаться на эту JS библиотеку.

На данный момент Preact используют такие компании как Lyft, Housing.com и m.uber.com. Команда разрабчиков Uber недавно написала статью о том, как Preact был использован для создания мобильной версии Uber, и насколько сильно он улучшил производительность приложения за счет минимального веса.

Другие методы API

В отличие от методов жизненного цикла, представленных выше (React вызывает их сам), методы, приведённые ниже, можно вызывать из компонентов.

Их всего два: и .

добавляет в очередь изменения в состоянии компонента. Также он указывает React, что компонент и его дочерние элементы должны быть повторно отрендерены с обновлённым состоянием. Этот метод используется для обновления интерфейса в ответ на обработчики событий и ответы сервера.

Думайте о , как о запросе, а не как о команде немедленного обновления компонента. Для увеличения производительности React может задержать его выполнение, а затем обновить несколько компонентов за один проход. React не гарантирует моментальное применение изменений в состоянии.

Метод не всегда обновляет компонент сразу. Он может группировать или откладывать обновление до следующего раза. Это делает чтение сразу после вызова потенциальной ловушкой. Вместо этого используйте или колбэк (), каждый из которых гарантированно вызывается после того как было применено обновление. Если вам нужно обновить состояние на основе предыдущего, используйте аргумент , описанный ниже.

всегда приводит к повторному рендеру, если только не возвращает . Если используются мутабельные объекты, и условие рендеринга не может быть реализовано в , вызывайте только при разнице следующего и предыдущего состояния. Это предотвратит ненужные повторные рендеры.

Первым аргументом передаётся функция , которая имеет следующий вид:

 — ссылка на состояние компонента при изменении. Объект состояния не должен мутировать. Изменения должны проявляться в виде нового объекта на основе входных данных из  и . Предположим, что мы хотели бы увеличить значение состояния с помощью :

Как , так и , полученные функцией обновления, гарантированно будут обновлены. Результат функции поверхностно объединяется с .

Второй параметр в  — дополнительный колбэк, который выполняется после того, как исполнится и произойдёт повторный рендер компонента. Мы рекомендуем использовать такой подход в .

В качестве первого аргумента , вместо функции, вы можете передать объект:

В нём образуется новое состояние после поверхностного объединения с . Например, установим количество товаров в корзине:

Эта форма записи также асинхронна, и несколько вызовов в течение одного цикла могут быть объединены вместе. Например, вам нужно увеличить количество элементов несколько раз в одном цикле. Результат этого можно представить так:

Последующие вызовы будут переопределять значения из предыдущих вызовов того же цикла. Из-за этого количество увеличится только один раз. В случае, если следующее состояние зависит от текущего, мы рекомендуем использовать форму функции обновления:

Для более подробной информации смотрите:

  • Руководство по состоянию и жизненному циклу
  • Продвинутый уровень: когда и почему группируются вызовы ?

По умолчанию при изменении состояния компонента или пропсов, происходит повторный рендер. Если ваш метод зависит от некоторых других данных, вы можете указать React необходимость в повторном рендере, вызвав .

Вызов приведёт к выполнению метода в компоненте, пропуская . Это вызовет обычные методы жизненного цикла для дочерних компонентов, включая каждого дочернего компонента. React по-прежнему будет обновлять DOM только в случае изменения разметки.

Чаще всего, не используется. Вместо этого используются в  данные из  и .

License

The MIT License (MIT)

Copyright (c) 2016, zenoamaro zenoamaro@gmail.com

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the «Software»), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED «AS IS», WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Состояние и setState()

Большинство из вас скорее всего уже использовали состояния React, они были даже в примере с КВП

Однако важно понимать, что при смене состояния React запустит процесс повторного отображения компонента (если не указать иное в )

Поговорим о том, как можно изменить состояние. Единственный способ сделать это — использовать метод . Он принимает объект и объединяет его с текущим состоянием. Помимо этого есть ещё несколько вещей, которые следует знать.

Во-первых, асинхронный. Это значит, что состояние не обновится сразу после вызова , что может привести к нежелательному поведению, которого мы сейчас научимся не допускать.

Взглянув на эту картинку можно увидеть, что мы сначала вызываем , а затем . Новое значение переменной должно быть равно 1, однако выводится 0. Что если мы хотим получить доступ к новому состоянию после того, как действительно обновит состояние?

Тут мы плавно переходим к следующей вещи, которую нужно знать о — этот метод может принимать callback-функцию. Исправим наш код:

Отлично, всё работает, на этом можно закончить, да? Не совсем. На самом деле, в данном случае мы не используем корректно. Вместо передачи объекта мы передадим методу функцию. Так обычно делается, когда для установки нового состояния используется текущее. Если это не ваш случай, то смело продолжайте передавать объект в . Исправим код ещё раз:

Вот CodePen для этого примера.

В чём смысл передачи функции вместо объекта? Поскольку  асинхронный, полагаться на него при создании нового значения немного рискованно. Например, к моменту запуска одного  другой  мог уже обновить состояние. Передача функции в  даёт два преимущества:

  1. Это позволяет создавать статичную копию состояния, которое никогда не изменится само по себе.
  2. Это поместит вызовы  в очередь, поэтому они будут запускаться по порядку.

Посмотрим на следующий пример, в котором попытаемся увеличить счётчик на 2, используя два последовательных вызова :

Сравните с кодом ниже:

CodePen для этого кода.

На первом изображении обе функции  напрямую используют , который, как мы узнали ранее, останется со значением 0 после вызова первого . Таким образом, конечное значение равно 1, а не 2, так обе функции  устанавливают значение счётчика равным 1.

На втором изображении мы передаём в  функцию, что гарантирует последовательный запуск обеих функций. Кроме этого, мы делаем снимок состояния, а не используем текущее, не обновлённое состояние. Теперь мы получили ожидаемый результат.

Вот и всё, что вам нужно знать о состояниях React.

Options

Theme

These stylesheets can be found in the Quill distribution, but for convenience they are also linked in React Quill’s folder. In a common case you would activate a theme by setting the theme . Pass a falsy value () to disable the theme.

ReactQuill theme="snow" /> // or "bubble", null to use minimal core theme

And then link the appropriate stylesheet (only link the CSS for the themes you want to use):

link rel="stylesheet" href="node_modules/react-quill/dist/quill.snow.css">
link rel="stylesheet" href="node_modules/react-quill/dist/quill.bubble.css">
link rel="stylesheet" href="node_modules/react-quill/dist/quill.core.css">

This may vary depending how application is structured, directories or otherwise. For example, if you use a CSS pre-processor like SASS, you may want to import that stylesheet inside your own.

Custom Toolbar

Default Toolbar Elements

Example Code

class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      text: "",
    }
  }

  modules = {
    toolbar:  }],
      ,
      ,
      ,
      
    ],
  },

  formats = ,

  render() {
    return (
      div className="text-editor">
        ReactQuill theme="snow"
                    modules={this.modules}
                    formats={this.formats}>
        ReactQuill>
      div>
    );
  }
}

export default MyComponent;

HTML Toolbar

You can also supply your own HTML/JSX toolbar with custom elements that are not part of the Quill theme.

Example Code

/*
 * Custom "star" icon for the toolbar using an Octicon
 * https://octicons.github.io
 */
const CustomButton = () => 

/*
 * Event handler to be attached using Quill toolbar module
 * http://quilljs.com/docs/modules/toolbar/
 */
function insertStar () {
  const cursorPosition = this.quill.getSelection().index
  this.quill.insertText(cursorPosition, "★")
  this.quill.setSelection(cursorPosition + 1)
}

/*
 * Custom toolbar component including insertStar button and dropdowns
 */
const CustomToolbar = () => (
  div id="toolbar">
    select className="ql-header" defaultValue={""} onChange={e => e.persist()}>
      option value="1">option>
      option value="2">option>
      option selected>option>
    select>
    button className="ql-bold">button>
    button className="ql-italic">button>
    select className="ql-color">
      option value="red">option>
      option value="green">option>
      option value="blue">option>
      option value="orange">option>
      option value="violet">option>
      option value="#d0d1d2">option>
      option selected>option>
    select>
    button className="ql-insertStar">
      CustomButton />
    button>
  div>
)

/*
 * Editor component with custom toolbar and content containers
 */
class Editor extends React.Component {
  constructor (props) {
    super(props)
    this.state = { editorHtml: '' }
    this.handleChange = this.handleChange.bind(this)
  }

  handleChange (html) {
  	this.setState({ editorHtml: html });
  }

  render() {
    return (
      div className="text-editor">
        CustomToolbar />
        ReactQuill
          onChange={this.handleChange}
          placeholder={this.props.placeholder}
          modules={Editor.modules}
        />
      div>
    )
  }
}

/*
 * Quill modules to attach to editor
 * See http://quilljs.com/docs/modules/ for complete options
 */
Editor.modules = {
  toolbar: {
    container: "#toolbar",
    handlers: {
      "insertStar": insertStar,
    }
  }
}

/*
 * Quill editor formats
 * See http://quilljs.com/docs/formats/
 */
Editor.formats = 

/*
 * PropType validation
 */
Editor.propTypes = {
  placeholder: React.PropTypes.string,
}

/*
 * Render component on page
 */
ReactDOM.render(
  Editor placeholder={'Write something or insert a star ★'}/>,
  document.querySelector('.app')
)

Custom Formats

The component has two types of formats:

  1. Custom formats created using Parchment and registered with your component’s Quill instance

Example Code

const ReactQuill = require('react-quill'); // CommonJS
import ReactQuill, { Quill } from 'react-quill'; // ES6
/*
 * Example Parchment format from
 * https://quilljs.com/guides/cloning-medium-with-parchment/
 * See the video example in the guide for a complex format
 */
let Inline = Quill.import('blots/inline');
class BoldBlot extends Inline { }
BoldBlot.blotName = 'bold';
BoldBlot.tagName = 'strong';
Quill.register('formats/bold', BoldBlot);

const formats =  // add custom format name + any built-in formats you need

/*
 * Editor component with default and custom formats
 */
class MyComponent extends React.Component {
  constructor(props) {
    this.formats = formats
    this.state = { text: '' }
  }

  handleChange(value) {
    this.setState({text: value})
  }

  render() {
    return (
      ReactQuill
        value={this.state.text}
        onChange={this.handleChange}
        formats={this.formats}
      />
    )
  }
}

The Data Flows Down

Neither parent nor child components can know if a certain component is stateful or stateless, and they shouldn’t care whether it is defined as a function or a class.

This is why state is often called local or encapsulated. It is not accessible to any component other than the one that owns and sets it.

A component may choose to pass its state down as props to its child components:

This also works for user-defined components:

The component would receive the in its props and wouldn’t know whether it came from the ’s state, from the ’s props, or was typed by hand:

This is commonly called a “top-down” or “unidirectional” data flow. Any state is always owned by some specific component, and any data or UI derived from that state can only affect components “below” them in the tree.

If you imagine a component tree as a waterfall of props, each component’s state is like an additional water source that joins it at an arbitrary point but also flows down.

To show that all components are truly isolated, we can create an component that renders three s:

Each sets up its own timer and updates independently.

In React apps, whether a component is stateful or stateless is considered an implementation detail of the component that may change over time. You can use stateless components inside stateful components, and vice versa.

Основные темы программы

Блок 1

Знакомство с React и его экосистемой.

В этом блоке мы начнем с того, на чем остановились в скринкасте по Реакт.
Научимся писать простые компоненты и узнаем, в чем принципиальное отличие React.js от других популярных фреймворков.
Создадим первые компоненты, используя декларативный подход, познакомимся с экосистемой, научимся использовать сторонние компоненты и работать с формами.

  • Разбираем как работает create-react-app.
  • Глубже знакомимся с Реактом, Virtual DOM, JSX.
  • Разбираем React Hooks, их отличия от стейта и lifecycle методов.
  • Разберем примеры тестирования компонент с помощью Jest и Enzyme.
  • Подключаем стили с css modules.
  • Учимся переиспользовать код с помощью наследования, декораторов и кастомных хуков.
  • Связь с DOM: keys & refs.
  • Подключаем сторонние компоненты.

Блок 2

Построение приложений с React: Redux.js

Когда приложения становятся сложнее и в них появляется интерактивность, приходиться задумываться про организацию бизнес-логики,
настраивать потоки данных и взаимодействие с сервером. В процессе построения простого новостного приложения мы детально
разберем самую популярную библиотеку для одностороннего потока данных, узнаем ее особенности и научимся использовать дев-тулзы.

  • Особенности Redux.js: функциональный подход, Redux dev tools.
  • Store как иммутабельный объект: Redux + Immutable.js.
  • Настраиваем синхронный поток с Redux, переиспользуем созданные ранее компоненты.
  • React-redux для связи компонентов с логикой.
  • Мемоизированные селекторы reselect.
  • Side-effects в Redux: создание и использование Middlewares.
  • Получение данных от сервера.
  • Асинхронные экшены с redux-thunk

Блок 3

React для SPA: react-router и продвинутые API Реакта

Разработка single-page applications – одно из основных направлений фронтэнда.
Мы разберем, как строить их, используя React.
Научимся использовать react-router и продвинутые элементы API React.JS.

  • Зачем нужен роутинг и как он устроен, проектируем структуру приложения.
  • Разбираем react-router v5.
  • Настраиваем вложенные роуты.
  • Выбираем и настаиваем history для нашего приложения.
  • Объединяем react-router и Redux.
  • Учимся обрабатывать серверные ошибки и декларативно управлять роутером.
  • Используем context – еще один механизм передачи данных.
  • Обзор Advanced API react-router.
  • Используем props.children для композиции компонентов.
  • Анимации в React, CSSTransitionGroup.

Начало работы с Preact

Preact API и его использование очень похожи на React, но есть несколько важных отличий, о которых нужно знать разработчикам.

Чтобы их продемонстрировать я разработал небольшое простое приложение с помощью Dribbble API, которое показывает последние разработки. Само приложение можно посмотреть здесь, а исходный код в Github.

Сейчас я расскажу о нескольких ключевых отличиях в разработке на Preact.

Для создания приложения на Preact нам понадобится Preact CLI – это проект от разработчиков Preact, который помогает новичкам быстрее разобраться с библиотекой. Preact CLI дает возможность генерировать веб приложения с такими функциями как:

  • Авто генерируемые Service Workers для оффлайн кэширования, работающие на sw-precache;
  • Автоматическое разделение кода на маршруты;
  • PRPL шаблон для быстрой загрузки;
  • Поддержка CSS модулей, LESS, SASS, Stylus (уроки по SASS для начинающих);
  • Автоматическое тестирование приложений, помощники в исправлении багов (12 Обязательных инструментов для Тестирования Кода);
  • Пре-рендеринг/рендеринг на серверной стороне.

Инструмент preact-cli поможет в написании Preact кода. Установить preact-cli можно с помощью следующей команды:

npm install -g preact-cli

Как только CLI успешно установится, создайте новое приложение, вбив в терминал следующую команду. preactdribbble – это название приложения. Вы можете назвать его как хотите, при этом перед ним может не быть префикса preact.

preact create preactdribbble

Это создаст новую папку с названием preactdribble, в которой будут все файлы, необходиыме для создания приложения. Откройте эту папку и давайте запустим приложение:

# start a live-reload/HMR dev server:
npm start

Эта команда запустит сервер Hot Module Reloading(HMR) по адресу http://0.0.0.0:8080 или http://localhost:8080.

Я не буду углубляться во все детали создания приложения, но я покажу разницу в разработке приложений с Preact.

Использование hyperscript

import { h, Component } from 'preact';

‘h’ – это функция, которая превращает JSX код в виртуальные DOM элементы. Это более обобщенная версия React.createElement.

Использование preact-router

// src/components/header/index.js
import { h, Component } from 'preact';
// Link is used to create links to other routes/pages
import { Link } from 'preact-router/match';
import style from './style';

export default class Header extends Component {
   render() {
      return (
         
      );
   }
}

preact-router создает компонент, который рендерит своих потомков, когда URL совпадает с их path. Он также автоматически добавляет элементы в router.

В блоке кода выше мы импортировали Link из preact-router/match. – это обычная ссылка, но она автоматически добавляет и удаляет classname “active” в зависимости от того, совпадает ли действительный URL.

Link компонент использует традиционный href атрибут в отличие от React, который использует атрибут to.

Использование (props, state) как аргументов в методе render()

// src/routes/home/index.js
render(props, { shots }) {
  return (
    
      
         
           {shots.map((item, i) => (
             
               
                 
                     
                 {item.title}
                 
                   
                       {item.user.name}
                   
                 
               
             
           ))}
         
       
    
  );
}

В render функции мы пользуемся преимуществами функции Preact, которые позволяют использовать shots.map вместо this.state.shots.map. В блоке кода выше данные из Dribbble используются для создания интерфейса приложения.

Создание шаблонов

preact-cli инструмент не работает с index.html файлом. Это может стать проблемой, если нужно отредактировать или добавить код в index.html. В есть раздел, названный templates. Шаблон используется для обработки страниц. Базовый шаблон можно посмотреть здесь. Нам нужно создать template.html внутри папки src, а затем использовать команду ниже, чтобы информировать Preact о том, что мы хотим использовать шаблон.

preact watch --template src/template.html

Вот и все. Это все новые вещи, которые увидит обычный пользователь React. Preact использует тот же API что и React, те же методы жизненного цикла и ту же мотодологию. Если вам комфортно разрабатывать на React, то вы готовы использовать Preact прямо сейчас!

Мотивация

При работе с React вы можете понимать как функцию, которая создаёт дерево React-элементов в какой-то момент времени. При последующем обновлении состояния или пропсов функция вернёт новое дерево React-элементов. Теперь React должен понять, как эффективно обновить UI, чтобы он совпадал с новейшим из деревьев.

Существует несколько общих решений алгоритмической проблемы трансформации одного дерева в другое за минимальное количество операций. Тем не менее, передовые алгоритмы имеют сложность порядка O(n3), где n — это число элементов в дереве.

Если бы мы использовали это в React, отображение 1000 элементов потребовало бы порядка миллиарда сравнений. Это слишком дорого. Взамен, React реализует эвристический алгоритм O(n), который основывается на двух предположениях:

  1. Два элемента с разными типами произведут разные деревья.
  2. Разработчик может указать, какие дочерние элементы могут оставаться стабильными между разными рендерами с помощью пропа .

На практике эти предположения верны почти для всех случаев.

Other Points for Consideration

Setting the language

Indicate the human language of page texts as screen reader software uses this to select the correct voice settings:

WebAIM — Document Language

Setting the document title

Set the document to correctly describe the current page content as this ensures that the user remains aware of the current page context:

WCAG — Understanding the Document Title Requirement

We can set this in React using the React Document Title Component.

Color contrast

Ensure that all readable text on your website has sufficient color contrast to remain maximally readable by users with low vision:

  • WCAG — Understanding the Color Contrast Requirement
  • Everything About Color Contrast And Why You Should Rethink It
  • A11yProject — What is Color Contrast

It can be tedious to manually calculate the proper color combinations for all cases in your website so instead, you can calculate an entire accessible color palette with Colorable.

Both the aXe and WAVE tools mentioned below also include color contrast tests and will report on contrast errors.

If you want to extend your contrast testing abilities you can use these tools:

  • WebAIM — Color Contrast Checker
  • The Paciello Group — Color Contrast Analyzer

Как отрендерить компонент

Пока что мы только встречали React-элементы, представляющие собой DOM-теги:

Но элементы могут описывать и наши собственные компоненты:

Когда React встречает подобный элемент, он собирает все JSX-атрибуты и дочерние элементы в один объект и передаёт их нашему компоненту. Этот объект называется «пропсы» (props).

Например, этот компонент выведет «Привет, Алиса» на страницу:

Давайте разберём, что именно здесь происходит:

  1. Мы передаём React-элемент в .
  2. React вызывает наш компонент с пропсами .
  3. Наш компонент возвращает элемент в качестве результата.
  4. React DOM делает минимальные изменения в DOM, чтобы получилось .

Modifying our decorator so that it will work asynchronously

A simple approach would be changing setTitle’s parameter to a callback function. Using it will now look like this:

@setTitle((props) => {    if(!props.user) return 'Loading profile...'    return `${prop.user.name}'s Profile`}class Profile extends React.Component {    ....}

And now, modifying our decorator:

const setTitle = (getTitle) => (WrappedComponent) => {   return class extends React.Component {      updateTitle = (props) => { // Check if the callback has returned something,          // and if so - update the title          const title = getTitle(props)          if(title) {             document.title = title          }      }      componentDidMount() {this.updateTitle(this.props)      }      componentWillReceiveProps(props) {this.updateTitle(props)      }      render() {         return       }   }}

Great! Now our decorator will make continuous checks every time it receives props and update the title accordingly. You can see the final result below:

Thanks for reading! This is just an experiment of mine, you can check out the source at https://github.com/gigobyte/react-document-title-decorator

If you want to see some other (more mature) solutions, check out:

  • https://github.com/gaearon/react-document-title
  • https://github.com/nfl/react-helmet

If you want to read more about decorators you can read this amazing article by Addy Osmani.

Using State Correctly

There are three things you should know about .

Do Not Modify State Directly

For example, this will not re-render a component:

Instead, use :

The only place where you can assign is the constructor.

State Updates May Be Asynchronous

React may batch multiple calls into a single update for performance.

Because and may be updated asynchronously, you should not rely on their values for calculating the next state.

For example, this code may fail to update the counter:

To fix it, use a second form of that accepts a function rather than an object. That function will receive the previous state as the first argument, and the props at the time the update is applied as the second argument:

We used an arrow function above, but it also works with regular functions:

State Updates are Merged

When you call , React merges the object you provide into the current state.

For example, your state may contain several independent variables:

Then you can update them independently with separate calls:

The merging is shallow, so leaves intact, but completely replaces .

No Breaking Changes

Before we continue, note that Hooks are:

  • Completely opt-in. You can try Hooks in a few components without rewriting any existing code. But you don’t have to learn or use Hooks right now if you don’t want to.
  • 100% backwards-compatible. Hooks don’t contain any breaking changes.
  • Available now. Hooks are now available with the release of v16.8.0.

There are no plans to remove classes from React. You can read more about the gradual adoption strategy for Hooks in the of this page.

Hooks don’t replace your knowledge of React concepts. Instead, Hooks provide a more direct API to the React concepts you already know: props, state, context, refs, and lifecycle. As we will show later, Hooks also offer a new powerful way to combine them.

If you just want to start learning Hooks, feel free to jump directly to the next page! You can also keep reading this page to learn more about why we’re adding Hooks, and how we’re going to start using them without rewriting our applications.

Ссылка на основную публикацию