React.js делаем код чище с централизованными PropTypes


Оглавление (нажмите, чтобы открыть):

ReactJS — Проверка типа с помощью PropTypes

По мере того, как ваше приложение растет, вы можете поймать множество ошибок с помощью typechecking. Для некоторых приложений вы можете использовать расширения JavaScript, такие как Flow или TypeScript, для typecheck для всего вашего приложения. Но даже если вы не используете их, React имеет некоторые встроенные возможности проверки типов. Чтобы запустить проверку типов на реквизитах для компонента, вы можете назначить специальное propTypes свойство:

PropTypes экспортирует ряд валидаторов, которые могут использоваться, чтобы убедиться, что данные, которые вы получили, действительны. В этом примере мы используем PropTypes.string. Если для опоры указано недопустимое значение, в консоли JavaScript будет показано предупреждение. По соображениям propTypesпроизводительности проверяется только в режиме разработки.

PropTypes

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

Требуется одиночный потомок

С помощью PropTypes.element вы можете указать, что только один ребенок может быть передан компоненту как потомок.

Значения по умолчанию Prop

Вы можете определить значения по умолчанию для вас props, назначив специальное defaultProps свойство:

Если вы используете преобразование Babel, подобное свойствам transform-class , вы также можете объявить defaultProps статическим свойством в классе компонентов React. Этот синтаксис еще не завершен, и для его работы в браузере потребуется выполнить этап компиляции.

React и ES6 — Часть 2, Классы React и инициализаторы свойств ES7

Это вторая статья из серии, в которой мы собираемся исследовать использование React с ECMAScript 6.

Другие части вы можете найти по ссылкам:

Код из этой статьи доступен на GitHub.

В первой статье мы начали с введения в ES6 и создания статичного компонента React, выводящего «Hello from ES6». Не очень интересно 🙂

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

Вот что мы увидим в результате:

Создание файла index.html

Начнем с создания простого HTML-файла:

Обратите внимание, что мы подключили фреймворк Foundation CSS с CDN. Это сделает наше приложение немного более симпотичным. Элемент div.root будет использоваться как контейнер для React приложения.

Gulpfile.js

Просто скопируйте содержимое gulpfile.js из предыдущей части. Никаких изменений на данном этапе не понадобиться.

Далее, запустите команду npm install (чтобы установить зависимости) и затем команду gulp. Gulp будет непрерывно следить за изменениями в файлах.

Основной компонент приложения

Вот что здесь происходит:

Строка 1. Мы импортируем библиотеку React и инициализируем переменную React.

Строка 2. Импортируем компонент CartItem, мы создадим его позже.

Строки 4-9. Передаем свойства в компонент CartItem (включая заголовок товара, изображение, начальную стоимость и цену).

Строки 11-17. Монтируем компонент CartItem в элемент DOM по классу .root.

Структура компонента CartItem

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

Добавьте следующий код в файл cartItem.jsx:

Строки 4-10. Это конструктор, появившийся в классах React. Первое, на что следует обратить внимание — это вызов функции super(props), он является обязательным. Следующий момент — вместо метода getInitialState(), разработчики React рекомендуют использовать своство this.state. Мы инициализировали состояние свойствами, переданными из app.jsx. Лично мне нравится это улучшение.

Строки 11-13. Объявление метода componentWillMount() (который в конечном счете является методом класса CartItem). В этом методе мы длаем пересчет общей стоимости. Чтобы рассчитать общую стоимость, мы используем метод recalculatePrice(), который умножает количество (хранится в состоянии компонента) на цену (является свойством).

Строки 14-20. Методы для увеличения или уменьшения количества элементов. Эти методы будут вызываться по нажатию на кнопки (см. скриншот приложения в начале статьи). Также обратите внимание, что мы используем в качестве функции обратного вызова метода this.setState() метод пересчета общей стоимости.

Метод render компонента CartItem

Добавьте следующий метод в класс CartItem:

Здесь мы используем только теги в формате JSX + состояние компонента и применяем Foundation CSS для декорирования.

Не беспокойтесь по поводу — я объясню это в следующей статье серии. А пока просто поверьте мне, что эта строка будет вызывать метод increaseQty() класса CartItem.

Итак, теперь у нас симпотичное приложение, взаимодействующее с пользователем. Не смотря на то, что это простой пример, он показывает, как написать компонент React, используя ECMAScript 6. Лично мне нравится новый синтаксис ES6.

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

Default Props и Prop Types в ES6 классах React

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

К счастью, это поддерживается React и называется Default Props и Prop Types. Вы можете познакомиться с ними поближе здесь.

После класса CartItem добавьте следующие строки:


В результате, если вы попытаетесь передать число в качестве свойства title, вы получите предупреждение в консоли. В этом сила валидации свойств React.

Добавление ES7 в проект

Вы можете задать вполне резонный вопрос — зачем я буду думать о ES7, когда ES6 только стандартизирован?

Я отвечу, что это взгляд в будущее. И начало использования таких особенностей, как инициализаторы свойств и декораторы.

Несмотря на то, что ES7 пока находится на совсем ранней стадии, есть ряд особенностей, которые уже реализованы в Babel. Эти экспериментальные особенности транслируются с ES7 в валидный ES5. Круто! Вы можете прочитать подробнее об этих экспериментальных особенностях на странице.

Чтобы добавить синтаксический сахар, нам необходимо внести небольшое изменение в строку 8 в gulpfile.js. Замените эту строку на код ниже:

Полный gulpfile.js вы можете взять из репозитория на GitHub.

Инициализаторы свойств ES7 для Default Props и Prop Types компонента React

В класс CartItem добавьте следующий код перед конструктором:

Этот код делает то же самое, что и код после определения класса, только в немного более аккуратным способом (на мой взгляд). Вы можете удалить код, относящийся к propTypes / defaultProps, который идет после определения класса CartItem, поскольку он больше не нужен.

Инициализаторы свойств ES7 для начального состояния компонента

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

Добавьте следующий код перед конструктором класса CartItem:

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

Готово. Вы можете взять финальный вариант cartItem.jsx из этой части серии на GitHub.

Заключение

В этой статье мы познакомились с реализацией компонентов React на ES6, а также кратко рассмотрели инициализаторы свойств ES7.

Следите за серией ES6 + React!

Для дополнительного чтения

Нашли опечатку? Orphus: Ctrl+Enter

© getinstance.info Все права защищены. 2014–2020

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

Что делать, если react-библиотека требует PropTypes?

Используем в проекте redux-saga-router.

Но, как только я собираюсь использовать линки:

Библиотека redux-saga-router начинает ругаться:
Uncaught TypeError: Cannot read property ‘string’ of undefined at createLink (createLink.js:56)

Это потому, что горе-разработчики сперва ввели в react PropTypes, а с 15.3.0 вынесли в отдельную библиотеку. А redux-saga-router об этом не знает и тупо пытается выполнить проверку:

Link.propTypes = <
to: _react.PropTypes.string.isRequired,
className: _react.PropTypes.string,
children: _react.PropTypes.any
>;

Собственно говоря как решить проблему, не отказываясь от библиотеки?

  • Вопрос задан более года назад
  • 97 просмотров

Хотелось бы прокомментировать, но не буду =)

Итак, у вас есть несколько путей:
1) делаете форк redux-saga-router и в ней изменяете везде (автозаменой в принципе, может будут трудные места, но
вряд ли) — подключение PropTypes
Затем либо использует свой форк (в package.json) прописывая урл до гитхаб репозитория, либо (правильнее) делаете pull request в библиотеку и помогаете другим.

2) пишите автору(ам) в issue, что пора бы пофиксить (но сначала проверьте, нет ли там уже такого issue, и может быть уже даже есть pull request, но его еще не приняли или есть чей-то уже рабочий форк и тд тп)

Макс, привет, с наступающим)

Затем либо использует свой форк (в package.json) прописывая урл до гитхаб репозитория, либо (правильнее) делаете pull request в библиотеку и помогаете другим. — можно тут поподробнее, ни разу такого не делал

Александр, привет, взаимно.
Можно указать свой логин на гитхабе + репозиторий + ветку, например, когда я ждал фикса uglifyjs для webpack, я уже взял чей-то чужой рабочий совет, сделал на его основе и моя зависимость выглядела так:
«webpack»: «maxfarseer/webpack#master»,

По форкам вообще (кнопочка): делается копия библиотеки, в нее вносятся изменения, потом делается pull request и там можно выбрать, куда отправить — выбирается webpack (уже оригинальный) и в какую ветку из какой. Вуаля.

React: PropTypes in stateless functional component

In React, I wrote a stateless functional component and now want to add Prop Type validation to it.

App component, rendering List :

As you can see in App , I am passing this.state.todos to List . Since this.state.todos is a string, I expected Prop Type validation to kick in. Instead, I get an error in the browser console because strings don’t have a method called map .


Why is the Prop Type validation not working as expected? Takin a look at this question, the case seems identical.

React.propTypes

(скучный, но небольшой теоретический перекур)

Перед выполнением данного урока, не забывайте, что PropTypes не работает с production версией реакта. Эта фича только для разработки, так как валидация — дорогая операция.

Давайте сломаем наш код:

Обновим страницу — видим сообщение об ошибке.

В принципе, все понятно — мы пытаемся вызвать метод map у undefined. У примитива undefined, как известно никаких методов нет — ошибка, получите распишитесь. Хорошо, что кода мало и мы быстро выяснили в чем проблема. Еще лучше, что есть возможность улучшить наше положение, добавив propTypes — специальное свойство, которое будет «валидировать» наш компонент.

Внесите изменения в компонент News />

Гораздо лучше! Исходя из текста ошибки нам сразу понятно куда копать: в render методе App, не указано свойство data, которое ожидается в News. Восстановим свойство data.

Вновь все работает, и наша консоль чиста.

Подробнее о propTypes

Согласно этому листингу, мы можем перевести правило, указанное в компоненте News /> :

React.PropTypes.array.isRequired — свойство должно быть массивом и оно обязательно должно быть!

Я вижу по глазам некоторых (да-да, вижу), что все это какая-то бесполезная лабуда. Итак понятно — есть ошибка, есть возможность тыкнуть на нее в дебаггере и посмотреть. Специально для вас, следующая ситуация: удалите из массива my_news автора, например в третьем элементе:

Никаких ошибок. Но наше приложение не работает так как надо. Кто виноват? Реакт? Backend-программист который прислал нам такие данные?

Программист, может и виноват. Но реакт точно нет. У нас получилось, что в this.props.data.author содержится undefined (переменнная не определена). Поэтому react так и поступил, и показал нам «ничего» (на скриншоте это только «двоеточие»).

Такую ошибку сложно отловить.

Мастер Йода рекомендует:  Зачем интернету usability

Добавьте propTypes в компонент Article />

В таком случае вы получите сообщение об ошибке:

React PropTypes в функциональном стиле

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

propTypes присваивается как статичное свойство компонента.

И если для классов в es6 предусмотрен синтаксический прием для статичных свойств, то в функциональных компонентах свойство propTypes присваивается динамически после определения функции.

Поэтому недостатком propTypes для stateless компонентов является его синтаксическая нативность. Если использовать Flow или TS, то валидацию типов можно осуществлять максимально компактно:

Одной из причин популярности stateless компонентов являются стрелочные функции, сокращающие написание функционального компонента на 14 символов.

Мелочь, а приятно. Причем, стрелочные функции не только содержат на 14 символов меньше, в отличии от анонимных классических, но и символы, участвующие в ее написании, что не маловажно, находятся по соседству на клавиатуре.

Использование стрелочной функции подразумевает компактность и функциональность. Но propTypes ломают всю красоту, для их написания требуется создание дополнительных конструкций. Мы вынуждены создавать вспомогательную переменную, разрывать цепочку вызовов и увеличивать количество кода минимум на 4 строки:

От чего теряется весь вкус синтаксического сахара. Поэтому я, воле не воле, пришел к мнению, что присоединение свойств к функциональным компонентам должно быть подвергнуто инкапсуляции. Так появился инструмент для работы с propTypes в функциональном стиле — assign-prop-types.

Теперь, вместо того, что бы описывать propTypes после написания компонента, и создавать свойство, непосредственно обращаясь к переменной компонента, вся работа с со свойствами компонента происходит в пределах одной цепочки вызовов и свойства описываются перед созданием компонента, а не после.

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

propTypes, defaultProps и contextTypes передаются в функцию как первые три аргумента. Я руководствовался тем простым опытом, что propTypes используются чаще всего, defaultProps реже и еще реже contextTypes. Именно в таком порядке assignPropTypes рассматривает свои параметры.

assignPropTypes( [propTypes ], [defaultProps], [contextTypes] ) : assigner

В ответ вы получаете другую функцию, готовую принять компонент, к которому эти свойства будут присоединены.

Функция assigner, возвращаемая assignPropTypes, может быть сохранена в переменную для повторного применения.

Но в большинстве случае вы ее будете вызывать сразу же после создания.

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

Сами имена свойств больше не нужны, больше не нужно писать propTypes, defaultProps, contextTypes. Тем самым мы экономим 9 символов propTypes , по 12 defaultProps и contextTypes , и цепочка вызовов избавляет от необходимости создавать временную переменную и указывать ее имя в коде минимум 3 раза (при создании, присвоение свойства и экспорте).

Все это делает код компактней, наглядней и функциональней. А дополнительные возможности функции, такие как комбинирование и расширяемость, могут пригодится при создании инструментов многократного применения.

Читайте подробнее об assign-prop-types на npm:

React.js: делаем код чище с централизованными PropTypes

Runtime type checking for React props and similar objects.

You can use prop-types to document the intended types of properties passed to components. React (and potentially other libraries—see the checkPropTypes() reference below) will check props passed to your components against those definitions, and warn in development if they don’t match.

If you prefer to exclude prop-types from your application and use it globally via window.PropTypes , the prop-types package provides single-file distributions, which are hosted on the following CDNs:

To load a specific version of prop-types replace 15.6.0 with the version number.


PropTypes was originally exposed as part of the React core module, and is commonly used with React components. Here is an example of using PropTypes with a React component, which also documents the different validators provided:

Refer to the React documentation for more information.

Migrating from React.PropTypes

Check out Migrating from React.PropTypes for details on how to migrate to prop-types from React.PropTypes .

Note that this blog posts mentions a codemod script that performs the conversion automatically.

There are also important notes below.

How to Depend on This Package?

For apps, we recommend putting it in dependencies with a caret range. For example:

For libraries, we also recommend leaving it in dependencies :

Note: there are known issues in versions before 15.5.7 so we recommend using it as the minimal version.

Make sure that the version range uses a caret ( ^ ) and thus is broad enough for npm to efficiently deduplicate packages.

For UMD bundles of your components, make sure you don’t include PropTypes in the build. Usually this is done by marking it as an external (the specifics depend on your bundler), just like you do with React.

This package is compatible with React 0.14.9. Compared to 0.14.8 (which was released in March of 2020), there are no other changes in 0.14.9, so it should be a painless upgrade.

This package is compatible with React 15.3.0 and higher.

What happens on other React versions?

It outputs warnings with the message below even though the developer doesn’t do anything wrong. Unfortunately there is no solution for this other than updating React to either 15.3.0 or higher, or 0.14.9 if you’re using React 0.14.

Difference from React.PropTypes : Don’t Call Validator Functions

First of all, which version of React are you using? You might be seeing this message because a component library has updated to use prop-types package, but your version of React is incompatible with it. See the above section for more details.

Are you using either React 0.14.9 or a version higher than React 15.3.0? Read on.

When you migrate components to use the standalone prop-types , all validator functions will start throwing an error if you call them directly. This makes sure that nobody relies on them in production code, and it is safe to strip their implementations to optimize the bundle size.

Code like this is still fine:

However, code like this will not work with the prop-types package:

It will throw an error:

(If you see a warning rather than an error with this message, please check the above section about compatibility.)

This is new behavior, and you will only encounter it when you migrate from React.PropTypes to the prop-types package. For the vast majority of components, this doesn’t matter, and if you didn’t see this warning in your components, your code is safe to migrate. This is not a breaking change in React because you are only opting into this change for a component by explicitly changing your imports to use prop-types . If you temporarily need the old behavior, you can keep using React.PropTypes until React 16.

If you absolutely need to trigger the validation manually, call PropTypes.checkPropTypes() . Unlike the validators themselves, this function is safe to call in production, as it will be replaced by an empty function:

See below for more info.

If you DO want to use validation in production, you can choose to use the development version by importing/requiring prop-types/prop-types instead of prop-types .

You might also see this error if you’re calling a PropTypes validator from your own custom PropTypes validator. In this case, the fix is to make sure that you are passing all of the arguments to the inner function. There is a more in-depth explanation of how to fix it on this page. Alternatively, you can temporarily keep using React.PropTypes until React 16, as it would still only warn in this case.

If you use a bundler like Browserify or Webpack, don’t forget to follow these instructions to correctly bundle your application in development or production mode. Otherwise you’ll ship unnecessary code to your users.

Подробное руководство по React.js в 2020 году

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

Компоненты (Components) — «строительные блоки» в React. Если исходить из контекста Angular, у компонентов много общего с Directives. Если вы используете другой контекст, то это, по существу, виджеты или модули.

Вы можете думать о компонентах как о коллекции HTML, CSS, JS и некоторых «внутренних данных», специфичных для этого компонента. Мне нравится сравнение компонентов с Kolaches в веб. В них есть все, что нужно, запакованное в восхитительный компонуемый сверток.

Компоненты определяются на «чистом» (pure) JavaScript или они могут быть определены на том, что команда React называет “JSX”. Если вы решите использовать JSX (который, вы, вероятнее всего, будете использовать, и это стандартно — мы также будем его использовать для нашего туториала), вам понадобится какой-то этап компиляции, чтобы преобразовать JSX в JavaScript. Но об этом мы поговорим позже.

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

Выше представлено изображение моего профиля Twitter. Если мы собираемся воссоздать эту страницу на React, мы разделили бы различные секции на разные компоненты (они выделены). Обратите внимание, что компоненты могут иметь вложенные компоненты внутри себя.

Мы могли бы назвать компонент слева (розовый) UserInfo . Внутри UserInfo компонента у нас есть еще один компонент (оранжевый), который мы могли бы назвать UserImages -компонентом.

Путь, по которому «работают» эти родительско-дочерние отношения — это наш UserInfo -компонент, или родительский компонент, в котором «живет» «состояние» (“state”) данных для него самого (UserInfo), так и для дочернего компонента UserImages .

Если мы хотим использовать какую-то часть данных родительского компонента в дочернем компоненте, то мы передадим эти данные дочернему компоненту в качестве атрибута.

В этом примере мы передаем UserImages-компоненту все изображения, которые есть у пользователя (которые в настоящее время «живут» в UserInfo -компоненте).

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

Эта иерархия parent / child делает управление нашими данными достаточно простым, потому что мы точно знаем, где находятся наши данные и мы не должны манипулировать ими в другом месте.

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


Я знаю, что это может выглядеть как «чересчур много», но вскоре вы увидите, насколько фундаментально важна каждая часть для создания надежных веб-приложений на React (и я также не шучу, когда я говорю, что хочу, чтобы это было «всесторонним» или исчерпывающим руководством).

На этом этапе вы должны понимать на «очень высоком уровне», как работает React. Теперь давайте перейдем к коду.

Создание первого компонента (JSX, Virtual DOM, render, ReactDOM.render)

Продолжим и напишем наш первый компонент на React.

Чтобы создать компонент на React, будем использовать ES6-класс. Если вы не знакомы с Классами, вы можете продолжить чтение, или узнать о них больше из других источников. (например, здесь — прим.переводчика)

Обратите внимание, что единственный метод в нашем классе — это render . Он является обязательным.

Причина — визуализация (render), описывающая пользовательский интерфейс (UI) нашего компонента. Таким образом, в этом примере текст, который будет отображаться на экране, где «рендерится» этот компонент, — Hello World!

Теперь изучим, что делает ReactDOM.

ReactDOM.render принимает два аргумента. Первый — компонент, который нужно отобразить, а второй — DOM-узел, где необходимо отобразить компонент.

Обратите внимание, мы используем ReactDOM.render , а не React.render . Это изменение в версии React.14, оно произведено, чтобы сделать React более «модульным». Это важно, если вы предполагаете, что React может отображать больше, чем просто DOM-элемент.

В примере выше мы просим React взять наш компонент HelloWorld и выполнить его render в элементе с ID root .

Мастер Йода рекомендует:  Криптография для самых маленьких шифрование с примерами на Python

Из-за родительских / дочерних отношений React, о которых мы говорили ранее, обычно использовать ReactDOM.render потребуется только единожды, потому что рендер «самого» родительского компонента уже предполагает отображение всех его вложенных дочерних компонентов.

Теперь на этой стадии вы можете почувствовать немного странное «бросание» «HTML» в свой JavaScript. С тех пор, как вы начали изучать веб-разработку, вам сказали, что вы должны оставить свою логику вне представления, то есть сохранить ваш JavaScript, не связанный с вашим HTML.

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

«HTML», который вы пишете в методе render, на самом деле не HTML, это то, что в React называется «JSX». JSX просто позволяет нам писать HTML-подобный синтаксис, который в конечном итоге преобразуется в легковесные объекты JavaScript. После чего уже React может принимать эти объекты JavaScript и от них формировать «виртуальный DOM» или представление JavaScript реального DOM («виртуальный DOM» — «легковесная копия реального DOM» — прим. переводчика). Это создает ситуацию с выигрышем, когда вы получаете доступность шаблонов с мощью JavaScript.

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

Теперь вы можете отказаться от фазы преобразования JSX -> JS и написать свои компоненты на React, например, как в коде выше. Но, как вы можете себе представить, это было бы довольно сложно. Я не знаю никого, кто не использует JSX. Для получения дополнительной информации о компиляции JSX посмотрите статьи на тему React Elements vs React Components.

До этого момента мы не выделяли особо важность этой новой виртуальной парадигмы DOM, в которую мы «запрыгиваем».

Причина, по которой команда React пошла этим путем, в том, что так как виртуальный DOM — это представление реального DOM, React может отслеживать разницу между актуальной виртуальной копией DOM, (вычисленной после изменений данных), и предыдущей, (вычисляется перед изменениями данных). Затем React изолирует изменения между старым и новым виртуальным DOM, после чего обновляет реальный DOM с необходимыми изменениями.

В более «дилетантских» выражениях, поскольку манипулирование реальным DOM происходит медленно («является более дорогостоящей операцией» — прим. переводчика), React способен минимизировать манипуляции с реальным DOM, отслеживая виртуальную копию DOM и обновляя реальный DOM только при необходимости и только с нужными изменениями.

Как правило, UI имеет множество состояний, затрудняющих управление состоянием в целом. Посредством ре-рендера виртуального DOM каждый раз, когда происходит какое-либо изменение состояния, React действительно упрощает размышления о том, в каком состоянии находится ваше приложение.

Процесс выглядит примерно так:

Некоторое пользовательское событие, которое изменяет состояние вашего приложения → ре-рендер виртуального DOM → Различие копий предыдущего виртуального DOM с новым → Обновление только реального DOM и только с необходимыми изменениями.

Поскольку это процесс преобразования от JSX к JS, необходимо настроить какую-то фазу трансформации во время разработки.

Во второй части я расскажу о Webpack и Babel для этого преобразования.

Давайте посмотрим на наш чек-лист «Самых важных частей React» и разберемся, где мы сейчас:

Мы идем в хорошем темпе. Все, что выделено «галочкой» — это то, что мы уже прошли, и вы сможете, по крайней мере, объяснить, как конкретно эти компоненты вписываются в экосистему React.

Добавление состояния к компоненту (state)

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

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

Возвращаясь к примеру Twitter, UserInfo -компонент, (выделенный розовым цветом), отвечает за управление состоянием (или данными) информации пользователя.

Если другому компоненту тоже нужно это состояние / данные, но это состояние не было прямым дочерним UserInfo , тогда вы создали бы другой компонент, который был бы прямым родителем UserInfo и другого компонента (или обоих компонентов, которым требуется это состояние). Затем вы «прокинете» состояние вниз в качестве props в дочерние компоненты. Другими словами, у вас есть мульти-компонентная иерархия, где общий родительский компонент должен управлять состоянием и передавать его дочерним компонентам через props.

Рассмотрим примерный компонент, который использует свой state:

В этом примере мы использовали новый синтаксис. Первое, что вы заметите, — это метод конструктора. Из определения выше, метод конструктора — «способ установки состояния компонента» (начального состояния — прим.переводчика). Другими словами, любые данные, которые вы помещаете в this.state внутри конструктора, будут частью состояния этого компонента.

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

Последнее о чем можно поговорить про state в том, что нашему компоненту нужна возможность изменять собственное внутреннее состояние. Мы делаем это с помощью метода, который называется setState. Помните ранее, когда мы говорили о ре-рендеринге виртуального DOM при каждом изменении данных?

Сигнал об уведомлении нашего приложения о том, что некоторые данные изменились → Ре-рендер виртуального DOM → Разница (diff) между предыдущей виртуальной копией DOM с актуальной → Обновление только реального DOM с необходимыми изменениями.

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

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

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

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

Когда вызывается handleChange , он будет вызывать setState , чтобы изменить наш username на значение, которое было введено в поле ввода (e.target.value) (предпочтительнее использовать e.currentTarget.value — прим.переводчика).

Помните, всякий раз, когда вызывается setState , React создает новый виртуальный DOM, выполняет «diff», а затем обновляет реальный DOM.

Теперь давайте посмотрим на наш render-метод. Мы добавили новую строку, содержащую поле ввода. Тип поля ввода, очевидно, будет text . Значение будет значением нашего username (имя пользователя), которое изначально было определено в конструкторе и будет обновлено в методе handleChange .


Обратите внимание, что есть новый атрибут, с которым вы, возможно, разньше не сталкивались — это onChange .

Атрибут onChange является «вещью из React», и он будет вызывать любой метод, который вы указываете, каждый раз, когда изменяется значение в поле ввода — в этом случае указанным нами методом был handleChange . (по аналогии с onchange в нативном javascript — прим.переводчика)

Процесс для кода выше будет выглядеть примерно так:

Пользователь вводит информацию в поле ввода (текст инпут) → вызывается handleChange → состояние нашего компонента меняется на новое значение → React повторно отображается виртуальную DOM → React считывает изменения → реальный DOM обновляется.

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

А пока, мы идем дальше! Если вы не можете объяснить то, что выделено «галочкой», прочитайте этот раздел еще раз.

Один совет по ДЕЙСТВИТЕЛЬНОМУ изучению React: не позволяйте себе пассивно читать, давая себе ложное чувство понимания материала (почему только React? Это работает везде — прим.переводчика).

Перейдите в песочницу CodeSandbox и попробуйте воссоздать примеры выше (или сделайте свои компоненты), не подглядывая в туториал. Это единственный способ начать обучение React. Это касается и этого урока, и следующего.

Получение state от родительского компонента (props, propTypes, getDefaultProps)

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

Это позволяет архитектуре React оставаться довольно простой. Управляйте state в высшем родительском компоненте, который нуждается в использовании специфических данных и, если у него есть потомок, которому также необходимы эти данные, «прокиньте» данные в качестве props-аргументов.

Вот очень простой пример использования props.

Обратите внимание, что в строке 9 мы имеем параметр name со значением «Tyler». Теперь в нашем компоненте мы можем использовать , чтобы получить «Tyler».

Давайте рассмотрим более продвинутый пример. Теперь у нас будет два компонента. Один — родитель, другой — потомок. Родитель должен отслеживать состояние и передавать часть этого состояния дальше до ребенка в качестве props.

Разберем родительский компонент.

В этом компоненте не так много нового. У нас есть изначальное состояние (initial state, задано в конструкторе) и мы передаем его часть другому компоненту.

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

Помните, что код, который возвращает метод render — это представление того, как должен выглядеть реальный DOM. Если вы не знакомы с Array.prototype.map, этот код может показаться вам немного странным. Все, что делает метод .map — создает новый массив, вызывает коллбек для каждого элемента массива и заполняет новый массив результатом вызова функции-коллбека для каждого элемента.

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

Что примечательно касательно .map, этот метод отлично вписывается в React (и идет «из коробки» в JavaScript). Таким образом, в нашем дочернем компоненте выше мы просто обернули имена в тэг
и сохраняем результат в переменной listItems.

Затем метод render возвращает неупорядоченный список ( ) со всеми нашими друзьями.

Рассмотрим еще пример, прежде чем закончим с props. Важно понимать, что везде, где есть данные, ими можно там же манипулировать. Это упрощает рассуждение о данных. Все методы getter / setter для определенной части данных всегда будут в том же компоненте, где были определены эти данные. Если вам нужно манипулировать какой-то частью данных вне того, где «живут» данные, вы передадите метод getter / setter в этот компонент в качестве props. Давайте посмотрим на такой пример.

Обратите внимание, что в нашем методе addFriend мы добавили новый способ вызова setState. Вместо того, чтобы передавать объект, мы передаем ему функцию, которая затем передается state. Всякий раз, когда вы устанавливаете новое состояние своего компонента на основе предыдущего, (как мы это делаем с нашим массивом друзей), вы хотите передать setState функцию, которая принимает текущее состояние и возвращает данные для слияния с новым состоянием.

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

Причина в том, что родительский компонент (FriendContainer) не знает (и не заботится) о новом знакомом, которого вы добавляете, он заботится обо всех ваших друзьях в целом (о массиве друзей).

Однако, поскольку мы придерживаемся правила манипулировать данными только из компонента, «которому не все равно», мы передали метод addFriend в наш компонент AddFriend в качестве props и мы вызываем его с new friend после вызова handleAddNew.

На этом этапе я рекомендую вам попытаться воссоздать эту же логику самостоятельно, используя приведенный выше код в качестве руководства.

Прежде чем мы пойдем дальше, хочу рассказать об еще двух возможностях React в отношении props. Это propTypes и defaultProps. Здесь я не буду вдаваться в подробности, потому что они довольно просты.

prop-types позволяют контролировать наличие или типы определенных props, переданных дочернему компоненту. С помощью propTypes вы можете указать, что требуются определенные props или что props являются определенным типом.

Начиная с React.15, PropTypes больше не включается в пакет React. Вам нужно будет установить их отдельно, запустив npm install prop-types .

defaultProps позволяют указать значение по умолчанию (или бэкап) для определенных props только в том случае, если эти props никогда не передаются в компонент.

Мастер Йода рекомендует:  Как определить оригинальность фотографии и была ли она отредактирована

Я изменил наши компоненты и теперь, используя propTypes, мы ожидаем что свойство addFriend будет функцией и что оно (свойство) будет передано в компонент AddFriend. Также, используя defaultProps, мы указали, что если массив друзей не передается компоненту ShowList, он будет пустым по умолчанию.

Итак, мы на последнем участке первой части.

Давайте посмотрим, что у нас осталось по плану.

Мы близки к финалу!

Жизненный цикл компонента (Component LifeCycle)

У каждого компонента, который вы создаете, будут свои события жизненного цикла, которые могут быть полезны для разных манипуляций. Например, если мы хотим сделать запрос AJAX для первого рендера и получить (fetch) данные, в каком lifecycle-методе это лучше сделать? Или, если бы мы захотели запустить какую-то логику, когда props изменились, как мы это сделаем?

Различные события жизненного цикла — ответы на оба вопроса.

Рассмотрим их ниже.

componentDidMount — вызывается один раз после первого рендера. К этому моменту компонент уже есть в DOM. Если вам нужно обратиться к виртуальному DOM — к вашим услугам this.getDOMNode(). Так же это лучший метод жизненного цикла компонента для работы с запросами на сервер.

componentWillUnmount — этот метод жизненного цикла вызывается непосредственно перед тем, как компонент будет удален из DOM. Здесь вы можете произвести необходимую очистку.

getDerivedStateFromProps — иногда вам нужно обновить состояние вашего компонента на основе «пришедших» props. Это метод жизненного цикла, в котором это можно сделать. Он будет принимать props и state, а возвращаемый объект будет объединен с текущим состоянием.

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


Для получения более подробной информации обратитесь к курсу Tyler McGinis React Fundamentals.

React.js: делаем код чище с централизованными PropTypes

Runtime type checking for React props and similar objects.

You can use prop-types to document the intended types of properties passed to components. React (and potentially other libraries—see the checkPropTypes() reference below) will check props passed to your components against those definitions, and warn in development if they don’t match.

If you prefer to exclude prop-types from your application and use it globally via window.PropTypes , the prop-types package provides single-file distributions, which are hosted on the following CDNs:

To load a specific version of prop-types replace 15.6.0 with the version number.

PropTypes was originally exposed as part of the React core module, and is commonly used with React components. Here is an example of using PropTypes with a React component, which also documents the different validators provided:

Refer to the React documentation for more information.

Migrating from React.PropTypes

Check out Migrating from React.PropTypes for details on how to migrate to prop-types from React.PropTypes .

Note that this blog posts mentions a codemod script that performs the conversion automatically.

There are also important notes below.

How to Depend on This Package?

For apps, we recommend putting it in dependencies with a caret range. For example:

For libraries, we also recommend leaving it in dependencies :

Note: there are known issues in versions before 15.5.7 so we recommend using it as the minimal version.

Make sure that the version range uses a caret ( ^ ) and thus is broad enough for npm to efficiently deduplicate packages.

For UMD bundles of your components, make sure you don’t include PropTypes in the build. Usually this is done by marking it as an external (the specifics depend on your bundler), just like you do with React.

This package is compatible with React 0.14.9. Compared to 0.14.8 (which was released in March of 2020), there are no other changes in 0.14.9, so it should be a painless upgrade.

This package is compatible with React 15.3.0 and higher.

What happens on other React versions?

It outputs warnings with the message below even though the developer doesn’t do anything wrong. Unfortunately there is no solution for this other than updating React to either 15.3.0 or higher, or 0.14.9 if you’re using React 0.14.

Difference from React.PropTypes : Don’t Call Validator Functions

First of all, which version of React are you using? You might be seeing this message because a component library has updated to use prop-types package, but your version of React is incompatible with it. See the above section for more details.

Are you using either React 0.14.9 or a version higher than React 15.3.0? Read on.

When you migrate components to use the standalone prop-types , all validator functions will start throwing an error if you call them directly. This makes sure that nobody relies on them in production code, and it is safe to strip their implementations to optimize the bundle size.

Code like this is still fine:

However, code like this will not work with the prop-types package:

It will throw an error:

(If you see a warning rather than an error with this message, please check the above section about compatibility.)

This is new behavior, and you will only encounter it when you migrate from React.PropTypes to the prop-types package. For the vast majority of components, this doesn’t matter, and if you didn’t see this warning in your components, your code is safe to migrate. This is not a breaking change in React because you are only opting into this change for a component by explicitly changing your imports to use prop-types . If you temporarily need the old behavior, you can keep using React.PropTypes until React 16.

If you absolutely need to trigger the validation manually, call PropTypes.checkPropTypes() . Unlike the validators themselves, this function is safe to call in production, as it will be replaced by an empty function:

See below for more info.

You might also see this error if you’re calling a PropTypes validator from your own custom PropTypes validator. In this case, the fix is to make sure that you are passing all of the arguments to the inner function. There is a more in-depth explanation of how to fix it on this page. Alternatively, you can temporarily keep using React.PropTypes until React 16, as it would still only warn in this case.

If you use a bundler like Browserify or Webpack, don’t forget to follow these instructions to correctly bundle your application in development or production mode. Otherwise you’ll ship unnecessary code to your users.

React и ES6 — Часть 2, Классы React и инициализаторы свойств ES7

Это вторая статья из серии, в которой мы собираемся исследовать использование React с ECMAScript 6.

Другие части вы можете найти по ссылкам:

Код из этой статьи доступен на GitHub.

В первой статье мы начали с введения в ES6 и создания статичного компонента React, выводящего «Hello from ES6». Не очень интересно 🙂

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

Вот что мы увидим в результате:

Создание файла index.html

Начнем с создания простого HTML-файла:


Обратите внимание, что мы подключили фреймворк Foundation CSS с CDN. Это сделает наше приложение немного более симпотичным. Элемент div.root будет использоваться как контейнер для React приложения.

Gulpfile.js

Просто скопируйте содержимое gulpfile.js из предыдущей части. Никаких изменений на данном этапе не понадобиться.

Далее, запустите команду npm install (чтобы установить зависимости) и затем команду gulp. Gulp будет непрерывно следить за изменениями в файлах.

Основной компонент приложения

Вот что здесь происходит:

Строка 1. Мы импортируем библиотеку React и инициализируем переменную React.

Строка 2. Импортируем компонент CartItem, мы создадим его позже.

Строки 4-9. Передаем свойства в компонент CartItem (включая заголовок товара, изображение, начальную стоимость и цену).

Строки 11-17. Монтируем компонент CartItem в элемент DOM по классу .root.

Структура компонента CartItem

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

Добавьте следующий код в файл cartItem.jsx:

Строки 4-10. Это конструктор, появившийся в классах React. Первое, на что следует обратить внимание — это вызов функции super(props), он является обязательным. Следующий момент — вместо метода getInitialState(), разработчики React рекомендуют использовать своство this.state. Мы инициализировали состояние свойствами, переданными из app.jsx. Лично мне нравится это улучшение.

Строки 11-13. Объявление метода componentWillMount() (который в конечном счете является методом класса CartItem). В этом методе мы длаем пересчет общей стоимости. Чтобы рассчитать общую стоимость, мы используем метод recalculatePrice(), который умножает количество (хранится в состоянии компонента) на цену (является свойством).

Строки 14-20. Методы для увеличения или уменьшения количества элементов. Эти методы будут вызываться по нажатию на кнопки (см. скриншот приложения в начале статьи). Также обратите внимание, что мы используем в качестве функции обратного вызова метода this.setState() метод пересчета общей стоимости.

Метод render компонента CartItem

Добавьте следующий метод в класс CartItem:

Здесь мы используем только теги в формате JSX + состояние компонента и применяем Foundation CSS для декорирования.

Не беспокойтесь по поводу — я объясню это в следующей статье серии. А пока просто поверьте мне, что эта строка будет вызывать метод increaseQty() класса CartItem.

Итак, теперь у нас симпотичное приложение, взаимодействующее с пользователем. Не смотря на то, что это простой пример, он показывает, как написать компонент React, используя ECMAScript 6. Лично мне нравится новый синтаксис ES6.

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

Default Props и Prop Types в ES6 классах React

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

К счастью, это поддерживается React и называется Default Props и Prop Types. Вы можете познакомиться с ними поближе здесь.

После класса CartItem добавьте следующие строки:

В результате, если вы попытаетесь передать число в качестве свойства title, вы получите предупреждение в консоли. В этом сила валидации свойств React.

Добавление ES7 в проект

Вы можете задать вполне резонный вопрос — зачем я буду думать о ES7, когда ES6 только стандартизирован?

Я отвечу, что это взгляд в будущее. И начало использования таких особенностей, как инициализаторы свойств и декораторы.

Несмотря на то, что ES7 пока находится на совсем ранней стадии, есть ряд особенностей, которые уже реализованы в Babel. Эти экспериментальные особенности транслируются с ES7 в валидный ES5. Круто! Вы можете прочитать подробнее об этих экспериментальных особенностях на странице.

Чтобы добавить синтаксический сахар, нам необходимо внести небольшое изменение в строку 8 в gulpfile.js. Замените эту строку на код ниже:

Полный gulpfile.js вы можете взять из репозитория на GitHub.

Инициализаторы свойств ES7 для Default Props и Prop Types компонента React

В класс CartItem добавьте следующий код перед конструктором:

Этот код делает то же самое, что и код после определения класса, только в немного более аккуратным способом (на мой взгляд). Вы можете удалить код, относящийся к propTypes / defaultProps, который идет после определения класса CartItem, поскольку он больше не нужен.

Инициализаторы свойств ES7 для начального состояния компонента

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

Добавьте следующий код перед конструктором класса CartItem:

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

Готово. Вы можете взять финальный вариант cartItem.jsx из этой части серии на GitHub.

Заключение

В этой статье мы познакомились с реализацией компонентов React на ES6, а также кратко рассмотрели инициализаторы свойств ES7.

Следите за серией ES6 + React!

Для дополнительного чтения

Нашли опечатку? Orphus: Ctrl+Enter

© getinstance.info Все права защищены. 2014–2020

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

Добавить комментарий