# Создание функционального компонента
- Создаем функцию компонент
- Знакомимся с хуками
- Практический пример создания функциональных компанент
## Чистые функции и их преимущества
1. Легко тестировать
2. Предсказуемость поведения. При одинаковых входных данных ответ всегда тот же.
```javascript
let ctx = 10;
function addUnpure(a, b) {
return ctx + a + b;
}
addUnpure(7, 5); // 22
addUnpure(7, 5); // 22
addUnpure(11, 15); // 36
ctx = 5;
addUnpure(7, 5); // 17
function add(a, b) {
return a + b;
}
```
## Создание функционального компонента
Функциональный компонент - обычная JavaScript функция. То, что она возвращает, совпадает с результатом вызова метода *render()* классового компонента
```javascript
function App () {
return (
<>
<Title className="app-title" title="Наведи на меня" style={{backgroundColor: 'red'}}>Pokemon List {process.env.REACT_APP_BOBIK}</Title>
<PokemonListLoader count={50} />
</>
);
}
```
## Класс или функция
В большинстве случаев в современном React проще использовать функциональные компоненты. В ряде случаев классы являются более подходящим инструментом:
1. Прямой доступ к DOM-дереву
2. Управление обновлением компонентов
Подробнее можно ознакомиться на странице [документации](https://ru.reactjs.org/docs/react-component.html)
## React Fragment в JSX
Вместо React.Fragment можно писать более удобную форму: <></>
## Хуки, useState
С помощью хуков можно забыть про проблемы потери контекста и управления им, а также this.state и метод this.setState.
## Жизненный цикл компонента, useEffect
useEffect вызывается единожды при условии, что параметры, от которых он зависит, не будут меняться. С каждым изменением значения в массиве параметров, функция в useEffect будет вызываться повторно.
```jsx
useEffect(() => {
(async () => {
setLoading(LOADING_PROGRESS);
const newData = await loadData(count);
setLoading(LOADING_END);
setData(newData.results);
})();
}, [count]);
```
## Правила использования хуков
1. Вызывать хуки только из React-компонентов
2. Использовать хуки только на верхнем уровне
3. Сохранить порядок вызова хуков и их количество
[Подробнее](https://ru.reactjs.org/docs/hooks-rules.html)
## Props Children
С помощью children можно передавать в компонент дочерние узлы
```jsx
import C from "classnames";
export const Title = (props) => {
const className = C('title', props.className);
return <h1 {...props} className={className}>{props.children}</h1>;
}
```
```jsx
<Title className="app-title" title="Наведи на меня" style={{backgroundColor: 'red'}}>Pokemon List {process.env.REACT_APP_BOBIK}</Title>
```
## Prop Types
Библиотека позволяет отследить правильность использования props на этапе разработки.
```jsx
import PropTypes from 'prop-types';
import { Pokemon } from '../molecules/Pokemon';
import { LOADING_PROGRESS, LOADING_END } from '../../constants.js';
export function PokemonList ({ loading, data = []}) {
return (<>
{loading === LOADING_PROGRESS && <span className="loading">Загрузка...</span>}
{loading === LOADING_END && <div className='pokemon-list'>
{data.map(({ name }, index) => <Pokemon key={index} name={name}/>)}
</div>}
</>);
}
PokemonList.propTypes = {
loading: PropTypes.bool,
data: PropTypes.arrayOf(PropTypes.object)
}
```
## Компоненты-обёртки (Proxy component)
Любой компонент, не имеющий состояния и внутренней логики. Отображает данные на основе переданных props
```jsx
export function Pokemon({ name }) {
return <div className='pokemon-list__item'>
<div className='pokemon-list__name'>
{name}
</div>
</div>;
}
```
## Компоненты высшего порядка (Higher-order component)
Функция, которая возвращает компонент
```jsx
import { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { loadData } from '../../api.js';
import { LOADING_INIT, LOADING_PROGRESS, LOADING_END } from '../../constants.js';
export function withPokemonLoader (Component) {
function PokemonListLoader({ count }) {
const [loading, setLoading] = useState(LOADING_INIT);
const [data, setData] = useState([]);
useEffect(() => {
(async () => {
setLoading(LOADING_PROGRESS);
const newData = await loadData(count);
setLoading(LOADING_END);
setData(newData.results);
})();
}, [count]);
return <Component loading={loading} data={data}/>;
}
PokemonListLoader.propTypes = {
count: PropTypes.number
};
return PokemonListLoader;
}
```
## Atomic Design
Концепция предлагает разделение частей дизайна на следующие составляющие
1. Атомы
2. Молекулы
3. Организмы
4. Шаблоны
5. Страницы
### Атомы
Мельчайшие элементы frontend-структуры
### Молекулы
Композиция на основе нескольких атомов
### Организмы
Композиция из нескольких молекул и атомов, может иметь состояние
### Шаблоны
Заготовка страницы, содержит композицию всех необходимых компонентов, но без данных
### Страницы
Шаблон с переданными ему данными