Fork me on GitHub

React.js - что это?!

Полезные ссылки

Дополнительные библиотеки

  • classnames - A simple JavaScript utility for conditionally joining classNames together.  ( yarn add classnames )

Create-React-App

npm i -g create-react-app

npm
npm init react-app my-app

Yarn
yarn create react-app my-app

npm start   - запуск приложения
npm run eject

При возникновении ошибки react-scripts: command not found :

yarn upgrade
yarn
yarn run start

Концепции React JS

  • virtual DOM

  • компонентная разработка

  • jsx - способ описать html-вёрстку в js

Основные способы создания компоненты

  • Расширить класс Component
class HelloWorld extends React.Component {
render() {
return <div>Hello!</div>;
}
}
  • Расширить класс PureComponent
class HelloWorld extends React.PureComponent {
render() {
return <div>Hello!</div>;
}
}
  • Написать функцию возвращающую jsx
function HelloWorld () {
return <div>Hello!</div>
}

Компоненты получают данные через props - атрибуты тега компоненты:

class Comment extends Component {
render() {
const {author, text} = props;
return (
<div>
<h4>{author}</h4>
<p>{text}</p>
</div>
);
}
}

class CommentList extends Component {
render() {
const comments = [
{text: 'hello!', author: 'Bill'},
{text: 'How are you?', author: 'Mary'}
];
return (
<ul>
{comments.map(comment => {
return <Comment author={comment.author} text={comment.text} />;
})}
</ul>
);
}
}

Состояние компоненты - this.state - Передать объект

         ```javascript
          this.setState({a: 1})
         ```


     
  • Передать функцию

    javascript this.setState(state => ({...state, a: 1}))

Функциональный компонент (созданных лишь одной функцией) -  нет состояния и функций жизненного цикла.

Потомки тегов

props.children  - для работы с детьми тегов.

Для работы со списками детей у реакта есть функция помощник React.Children.map, и если вы хотите обернуть каждого ребенка в дополнительный тег:

const Parent = props => (
<div>
<p>Parent</p>
{React.Children.map(props.children, child => <p>{child}</p>)}
</div>
);

Порядок вызовов методов компоненты


Монтирование компоненты

  • constructor

  • componentWillMount

  • render

  • componentDidMount

Обновление компоненты

  • compoentWillReceiveProps

  • shouldComponentUpdate

  • componentWillUpdate

  • render

  • componentDidUpdate

Удаление компоненты

  • componentWillUnmoun

  • forceUpdate()

По умолчанию, компонент вызывает метод render только если он получает новые props, меняет state или монтируется. Есть возможность вызвать в ручную метод render, с помощью forceUpdate. В нормальной ситуации не стоит вызывать метод, а когда покажется что стоит, нужно подумать еще 7 раз.

  • defaultProps

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

  • displayName

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

События в React

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

class Form extends React.Component {
state = {
value: ''
};
handleOnChange = event => {
this.setState({value: event.target.value});
};
render() {
return (
<div>
<p>{this.state.value}</p>
<input value={this.state.value} onChange={this.handleOnChange} />
</div>
);
}
}

Cуществуют методы onInput для получения событий input, onSubmit для тегов form, onClick, onFocus для событий получения фокуса и onBlur для событий удаления фокуса.

Cписок обработчиков событий для мышки:

onClick, onContextMenu, onDoubleClick, onDrag, onDragEnd, onDragEnter, onDragExit, onDragLeave, onDragOver, onDragStart, onDrop, onMouseDown, onMouseEnter, onMouseLeave, onMouseMove, onMouseOut, onMouseOver, onMouseUp.

Все обработчики событий получают синтетическое событие, если нужно остановить баблинг события, можно воспользоваться event.preventDefault() иди event.stopPropagation().

Если нужно передать событие, и воспользоваться им в асинхронном коде, в следующих тиках — необходимо вызвать метод event.persist() чтобы реакт отдал вам это событие.

Проверка типов PropTypes

Для установки нужно выполнить команду:

yarn add prop-types

Чтобы перечислить типы параметров компоненты:

  1. Добавить параметр propTypes к уже созданному классу или функции:
import PropTypes from 'prop-types';
import React from 'react';

const Greeting = ({name}) =>
<p>Hi, {name}!</p>
Greeting.propTypes = {
name: PropTypes.string,
name2: PropTypes.string.isRequired  //  isRequired указывает что переменная обязательно
}
  1. Для классов можно объявить статическую внутреннюю переменную propTypes для того, чтобы объявлять необходимые типы прямо в компоненте:

```javascript import PropTypes from 'prop-types'; import React from 'react';

class UserCard extends React.Component { static propTypes = { user: PropTypes.shape({ firstName: PropTypes.string.isRequired, lastName: PropTypes.string.isRequired, email: PropTypes.string.isRequired }).isRequired, isAdmin: PropTypes.boolean.isRequired };

defaultProps = { isAdmin: false };

render() { return ... } } ```

Если указаны значения в defaultProps, а компонента не получила значений от родителя для PropTypes с флагом isRequired,значение будет взято из defaultProps.

Список типов, которые доступны в PropTypes:

MyComponent.propTypes = {
// Все PropTypes опциональны, и делают проверку только на соответствие типа
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
optionalString: PropTypes.string,
optionalSymbol: PropTypes.symbol,
// Этот тип описывает любой элемент, который реакт может отрендерить в jsx
optionalNode: PropTypes.node,
// Реакт компонент
optionalElement: PropTypes.element,
// Также можно проверить, является ли тип экземпляром конкретного класса
optionalMessage: PropTypes.instanceOf(Message),
// Позволяет проверить, что значение является одним из списка
optionalEnum: PropTypes.oneOf(['News', 'Photos']),
// Переменная может быть одной из перечисленных типов
optionalUnion: PropTypes.oneOfType([
PropTypes.string,
PropTypes.instanceOf(Message)
]),
// Переменная должна быть списком элементов с конкретным типом
optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
// Объект должен содержать значения определенного типа
optionalObjectOf: PropTypes.objectOf(PropTypes.number),
// Проверка ключей объекта на соответствие типа
optionalObjectWithShape: PropTypes.shape({
color: PropTypes.string,
fontSize: PropTypes.number
}),
// Пометить переменную, как обязательную
requiredFunc: PropTypes.func.isRequired,
// Переменная может быть любого типа
requiredAny: PropTypes.any.isRequired
};

Порталы

Когда нужно отрендерить компонент не в текущем месте дерева компонент, а отдельно, например, модальные окна, тултипы, попапы. Такого рода элементы находятся в самом конце тега body, чтобы быть выше остальных элементов.

В случае порталов, нам необходимо вернуть ReactDOM.createPortal:

class ModalWindow extends Component {
render() {
return ReactDOM.createPortal(this.props.children, this.props.domNode);
}
}

class App extends Component {
render() {
return (
<ModalWindow domNode={document.querySelector('#modal')}>
<p>It is modal window</p>
</ModalWindow>
);
}
}

Первый аргумент -  компонент реакта; Вторым — DOM объект, в котором реакт разместит этот компонент.

Сcылки ref

Существует несколько оправданных случаев использования ссылок ref:

  • Управление фокусом, выделением текста или воспроизведением мультимедиа

  • Переключение необходимой анимации

  • Интеграция со сторонними DOM библиотеками

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

React-роутинг (динамический роутинг) установка

yarn add react-router-dom

Также существует пакет react-router-native для работы на мобильных устройствах вместе с react-native, и react-router, который содержит общий код для этих библиотек.

Также существует пакет react-router-native для работы на мобильных устройствах вместе с react-native, и react-router, который содержит общий код для этих библиотек.

Обернуть корневой компонент с помощью BrowserRouter: import {BrowserRouter} from 'react-router-dom';

ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);

Вот и реализация роутинга:

import React from 'react';
import {Link, Route} from 'react-router-dom';

const Home = () => <p>Home page</p>;
const About = () => <p>About page</p>;
const Topics = () => <p>Topics page</p>;

const App = () => (
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/topics">Topics</Link></li>
</ul>
<hr />
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/topics" component={Topics} />
</div>
);
export default App;

Для работы с переходами по страницам используется компонента Link, которая превращается в тег a, но реакт-роутер обрабатывает переход так, чтобы не было перезагрузки страницы. Роутер ловит событие клика на ссылку, отменят его, и делает push в window.history, браузер переходит на новый путь без перезагрузки страницы.

Компоненты, которые возвращает компонент Route получают в props дополнительный параметры:

match = {
isExact: true,
params: {},
path: '/topics',
url: '/topics'
}

location = {
hash: "",
pathname: "/topics",
search: "",
state: {}
}
  • Match содержит данные по соответствию пути и роута и дополнительные параметры.

  • IsExact говорит о том, что путь в браузерной строке полностью соответствует роуту.

  • В params находятся дополнительные ключи, которые можно спарсить из роута, если путь использует регулярное выражение или /topics/:id.

  • Path — это путь с которым проводили сравнение. Полезен для создания вложенных Route.

  • Url — это полный путь, полезен для создания вложенных Link.

History — это объект, который использует библиотеку history (https://github.com/ReactTraining/history) для удобной работы с сессией и историей переходов. Также реакт-роутер может работать с якорными переходами, когда url меняется не целиком, а только после якоря #

  • length — длина истории, количество location в стеке истории.

  • action — текущее действие, выполненное с историей: PUSH, REPLACE или POP. Соответствует переходу на страницу, замене текущей страницы и переходу назад.

  • location — текущая локация, соответствует location, переданному отдельно через prop.

  • push — функция, с помощью которой происходит переход по истории.

  • replace — функция для замены текущего пути.

  • go(n) — функция для указания номера пути в стеке истории путей.

  • goBack — функция для перехода назад (go(-1)).

  • goForward — функция для перехода вперед(go(1)).

  • block(promt) — функция для остановки перехода пользователя, которая вызовет окно confirm с просьбой не покидать страницу ("Вы уверены что хотите закрыть страницу?").

компонент Switch и редиректы

<Switch>
<Route path="/" exact component={Home} />
<Redirect from="/old-match" to="/will-match" />
<Route path="/will-match" component={WillMatch} />
<Route component={NoMatch} />
</Switch>;

Компонент Switch последовательно смотрит детей и сравнивает их path и флаги exact и strict.

social