Skip to content

Instantly share code, notes, and snippets.

@nikneroz nikneroz/react_redux.md
Last active Oct 12, 2018

Embed
What would you like to do?
Лекция №2: React & Redux.

React

Функциональные и классовые компоненты

const WelcomeComponent = (props) =>
  <h1>Hello, {props.name}</h1>
class WelcomeComponent extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

Передача аттрибутов

const WelcomeComponent = (props) =>
  <h1>Hello, {props.name}</h1>

const element = <WelcomeComponent name="Tele2" />
ReactDOM.render(
  element,
  document.getElementById('root')
)

Reusable Components

https://abraxabra.ru/react.js/bystryy-start/react-js-komponenty-i-svoystva/

const Welcome = (props) =>
  <h1>Hello, {props.name}</h1>

const App = (props) => 
  <div>
    <Welcome name="Sara" />
    <Welcome name="Cahal" />
    <Welcome name="Edite" />
  </div>

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

Class constructor

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

React lifecycle

Обработка пользовательского ввода

Рендер списков и использование key

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li key={number.toString()}>
    {number}
  </li>
);
const todoItems = todos.map((todo) =>
  <li key={todo.id}>
    {todo.text}
  </li>
);

Использование map in JSX

function NumberList(props) {
  const numbers = props.numbers;
  return (
    <ul>
      {numbers.map((number) =>
        <ListItem key={number.toString()}
                  value={number} />
      )}
    </ul>
  );
}

Реактивность =)

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

К примеру, в императивном программировании присваивание a = b + c будет означать, что переменной a будет присвоен результат выполнения операции b + c, используя текущие (на момент вычисления) значения переменных. Позже значения переменных b и c могут быть изменены без какого-либо влияния на значение переменной a.

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

Пример - https://codepen.io/gaearon/pen/WZpxpz?editors=0010

Передача children

C чего начать?

Разделение логики

import React from 'react';

const MyComponents = {
  DatePicker: function DatePicker(props) {
    return <div>Imagine a {props.color} datepicker here.</div>;
  }
}

function BlueDatePicker() {
  return <MyComponents.DatePicker color="blue" />;
}

Нативная проверка типов

import PropTypes from 'prop-types';

class Greeting extends React.Component {
  render() {
    return (
      <h1>Hello, {this.props.name}</h1>
    );
  }
}

Greeting.propTypes = {
  name: PropTypes.string
};

Руководство по внедрению типизации - https://reactjs.org/docs/static-type-checking.html

Передача контекста по дереву children

import PropTypes from 'prop-types';

class Button extends React.Component {
  render() {
    return (
      <button style={{background: this.context.color}}>
        {this.props.children}
      </button>
    );
  }
}

Button.contextTypes = {
  color: PropTypes.string
};

class Message extends React.Component {
  render() {
    return (
      <div>
        {this.props.text} <Button>Delete</Button>
      </div>
    );
  }
}

class MessageList extends React.Component {
  getChildContext() {
    return {color: "purple"};
  }

  render() {
    const children = this.props.messages.map((message) =>
      <Message text={message.text} />
    );
    return <div>{children}</div>;
  }
}

MessageList.childContextTypes = {
  color: PropTypes.string
};

Фрагменты

render() {
  return (
    <React.Fragment>
      <ChildA />
      <ChildB />
      <ChildC />
    </React.Fragment>
  );
}

Порталы

Используются при необходимости рендера вне заданной структуры DOM. Документация. https://reactjs.org/docs/portals.html

Redux

Тестовое задание - https://redux.js.org/basics/example-todo-list Материалы для самостоятельного изучения - https://rajdee.gitbooks.io/redux-in-russian/content/docs/introduction/Ecosystem.html

Зачем нам Redux?

Глоссарий - https://rajdee.gitbooks.io/redux-in-russian/content/docs/Glossary.html

  • Состояние (State)
  • Действие (Action) - Вызов функции изменения состояния
  • Редюсер (Reducer) - Функция которая изменяет состояние
  • Функция-диспетчер (Dispatching Function) - It refers to the control of processes of operation planning, giving operation order and controlling operations in the manufacturing site.
  • Генератор действия (Action Creator) - Фабрика для создания actions
  • Асинхронное действие (Async Action) - Promise например.
  • Мидлвэр (Middleware) - функция высшего порядка, которая создает функцию-диспетчер (dispatch function), возвращающую новую функцию-диспетчер.
  • Хранилище (Store)
  • Генератор хранилища (Store creator)
  • Расширитель хранилища (Store enhancer) - см. middleware

3 принципа - https://rajdee.gitbooks.io/redux-in-russian/content/docs/introduction/ThreePrinciples.html

  • Source of truth - Состояние всего вашего приложения сохранено в дереве объектов внутри одного хранилища.
  • Change action - Единственный способ изменить состояние — это применить действие — объект, который описывает, что случится.
  • Clean functions - Для определения того, как дерево состояния будет трансформировано действиями, вы пишете чистые редюсеры.

Reducer — это просто чистые функции, которые берут предыдущее состояние и действие и возвращают новое состояние. Не забывайте возвращать новый объект состояния вместо того, чтобы изменять предыдущее.

Связь React & Redux

import React from 'react'
import { withRouter } from 'react-router-dom'

import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { Link } from 'react-router-dom'

class Navigation extends React.Component {
  componentWillMount() {
    this.props.getProfileInformation()
  }
  
  routes() {
    return [
      {
        route: '/profile/password',
        name: 'Изменение пароля'
      },
      {
        route: '/profile/info',
        name: 'Профиль'
      }
    ]
  }

  render () {
    return (
      const { userName } = this.props
      <Container>
        { userName }
        <div>
          {
            this.routes().map((item, i) =>
              <NavLink to={item.route} key={i}>
                {item.name}
              </NavLink>
            )
          }
        </div>
      </Container>
    )
  }
}

const mapDispatchToProps = dispatch => bindActionCreators({
  getProfileInformation,
}, dispatch)

const mapStateToProps = store => ({
  userName: store.profile.name
})

export default connect(mapStateToProps, mapDispatchToProps)(withRouter(Navigation))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.