# React basics

### JSX

`JSX` - это синтаксическое расширение для JavaScript (функции **CreateElement**)

```
<MyButton color="blue" shadowSize={2} action={this.action}>
  Click Me
</MyButton>
```

```
React.createElement(
  MyButton,
  { color: 'blue', shadowSize: 2 },
  'Click Me'
)
```

* `Babel` компилирует `JSX` в вызовы `React.createElement()`
* Теги начинаются с заглавной буквы (чтобы отличить React-компоненты от html тегов)
* т.к. неявно вызывается функция `React.createElement`, в файле должен быть `import React from 'react'`
* атрибуты: class === `className`, for === `htmlFor`
* встраивание пользовательского ввода в JSX является безопасным (не допускает XSS-атак) - потому что все преобразуется в строку, а не выполняется

### Presentation vs Container components

* `Container`
  * делают API запросы
  * подключены к Store,
  * часто созданы через `class`
  * используют lifecycle hooks
* `Presentation`
  * получают данные через `props` и отрисовывают
  * редко могут иметь свой локальный state, но это состояние UI, а не бизнес-данных (например, выбран ли checkbox)
  * часто созданны через `function`

### Lifecycle

![](https://3408508746-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lis5JLcnSD2vdYdyQ3U%2F-LkQ1d2jX78DZKNTKxn4%2F-LkQ1dYtUWCLh00c0khX%2Fimage.png?alt=media\&token=364b46d9-fb3d-4014-8fc1-bcde1daa2036)

* Mounting
  * `constructor(props)` - (не обязательный,, если не нужно инициализировать там state)
  * static `getDerrivedStateFromProps(props, state)` (возвращает объект, который и будет this.state)
  * render()
  * `componentDidMount()` (хорошее место для API-запросов, подписок на события)
* Updating
  * static `getDerrivedStateFromProps(props, state)`
  * `shouldComponentUpdate()` (если вернет false, render и все нижние хуки не вызовутся)
  * render()
  * `getSnapshotBeforeUpdate()` - перед коммитом изменений в реальный DOM, возвращенное из метода значение станет 3-м аргументом
  * `componentDidUpdate(prevProps, prevState, snapshot)`
* Unmounting
  * `componentWillUnmount()` - (отписаться от событий, удалить таймеры, ...)
* Error Handling
  * static `getDerivedStateFromError(error)` - возвращает значение для изменения state (тут не должно быть side-effects)
  * `componentDidCatch(error, info)` - можно использовать для side-effects, например залогировать ошибку в логгер

### State vs Props

* Props

  * передаются в компонент из-вне
  * так ще компонент может иметь дефолтные props

  ```
  static defaultProps = {
    theme: "secondary",
    label: "Button Text"
  };
  ```

  * props нельзя изменить (однонаправленный поток данных, сверху-вниз)
* State
  * хранит внутреннее состояние компонента
  * для того, чтобы хранить информацию между рендерами
  * при изменении состояния происходит render
  * setState() асинхронный, иммутабельный, можно внутрь передавать функцию или объект (если не зависим от прошлого состояния)

### Refs

> Refs provide a way to access DOM nodes or React elements created in the render method.

```
class Component extends React.Component {
  constructor() {
    this.inputRef = React.createRef();
  }

  handleSubmit = () => {
    this.inputWrapper.current.focus();
  }

  render() {
    return (
      <div onClick={this.handleSubmit}>
        <input type="text" ref={this.inputRef} />
      </div>
    )
  }
}
```

**#forwarding Refs**

> Ref forwarding is a technique for automatically passing a ref through a component to one of its children

### Events

* React events are named using camelCase, rather than lowercase.
* with JSX you pass a function as the event handler, rather than a string.
* React uses a synthetic event. React defines these synthetic events according to the W3C spec, so you don’t need to worry about cross-browser compatibility

```
function handleClick(e) {
    e.preventDefault();
    console.log('The link was clicked.');
  }
```

**#SyntheticEvent**

> SyntheticEvent, a cross-browser wrapper around the browser’s native event. It has the same interface as the browser’s native event, including `stopPropagation()` and `preventDefault()`, except the events work identically across all browsers.

### Forms

* uncontrolled input - will use `ref` to get the form values.

```
submitFormHandler = event => {
  event.preventDefault();
  console.dir(this.refs.name.value); //will give us the name value
}

render() {
  return (
      <div>

        <form onSubmit={this.submitFormHandler}>
          <div>
            <input type="text" name="name" ref="name" />
          </div>
        </form>

      </div>
  );
}
```

* controlled input (+ validation, notifications)

```
import React, { Component } from 'react';

class FormComponent extends Component {
  constructor () {
    this.state = {
      email: ''
    }
  }
  
  changeHandler = event => {
    this.setState({
      email: event.target.value
    });
  }

  render () {
    return (
      <form>
          <input type="email" 
                 name="email"   
                 value={this.state.email} 
                 onChange={this.changeHandler} 
          />
      </form>
    );        
  }
}

export default FormComponent;
```

### Data fetching

> React itself doesn’t have any allegiance to any particular way of fetching data.

* axios (promises)
* fetch (browser api)

```
componentDidMount() {
    axios.get(`http://www.reddit.com/r/${this.props.subreddit}.json`)
      .then(res => {
        const posts = res.data.data.children.map(obj => obj.data);
        this.setState({ posts });
      });
  }
```
