ABOUT US

LeadScanr finds leads from social media in real-time

Front-End, ML

Full stack

Ievgen Terpil

Vyacheslav Pytel

chapter 0

INTRO

INITIAL POINT

- Framework without improvements

- File structure

- Scalability

- Build tools

IDEAL APP

- framework with community

- easy to implement new features

- easy to support

- easy to test

- localization

- build tools

chapter 1

HYPE

FLUX

REduX

React Europe

REduX

(state, action) => state 

REDUX

REduX

{
    type: 'DEPOSIT',
    value: 10
}

Action

REduX

function counter(state = 0, action) {
  switch (action.type) {
  case 'DEPOSIT':
    return state + action.value
  case 'WITHDRAW':
    return state - action.value
  default:
    return state
  }
}

Reducer

Changes are made with pure functions

REduX

State

state tree

Single source of truth

REduX

const store = 
    createStore(reducer, initialState)

store.subscribe(render)

// -----------------------------------
store.dispatch(action)

STore

State is read-only

REduX

const App = ({ state }) => {
    <div>
        Balance: {state}
    </div>
}

VIEW

VIEW LAYER

........

REACT AS VIEW LAYER

REACT AS VIEW LAYER

Account = ({ balance, onDepositClick }) => {
    <div>
        <button onClick={onDepositClick}>
            deposit
        </button>
        <div>Balance: {balance}</div>
    </div>
}

REACT AS VIEW LAYER

connect(
  mapStateToProps,
  mapDispatchToProps
)(Account)
function mapStateToProps(state, ownProps) {
  return { balance: state.balance }
}
function mapDispatchToProps(dispatch) {
  return {
    onDepositClick: () => dispatch(deposit())
  }
}

REACT AS VIEW LAYER

@connect(({ Subscriptions, Profile }) => ({
  currentPlan: Subscriptions.get('currentPlan'),
  userName: Profile.get('userName')
}))
export default class Subscriptions extends React.Component {

  static propTypes = {
    dispatch: PropTypes.func.isRequired,
    userName: PropTypes.string,
    currentPlan: PropTypes.object
  }

  ...

}

our case with ES7

decorator

DUMB AND SMART

Dumb (Presentational)

Smart (Container)

real view

uses only props

functional components

DOM markup and styles 

logic

Redux's connect

binds cb for dumb

DOM markup and styles

 

 

reusable

your mini Bootstrap

SIDE EFFECTS

SIDE EFFECTS

SIDE EFFECTS - BASE APPROACH

{ type: 'FETCH_ACCOUNT_REQUEST' }
{ type: 'FETCH_ACCOUNT_SUCCESS', account: { ... } }
{ type: 'FETCH_ACCOUNT_FAILURE', error: 'Oops' }

actions

action creators

function receiveAccount(account) {
  return {
    type: FETCH_ACCOUNT_SUCCESS,
    account
  }
}

SIDE EFFECTS - BASE APPROACH

let getAccount = id => dispatch => {
  dispatch(requestAccount(id));
  return fetch('/account', id)
    .then(account => dispatch(receiveAccount(account)))
    .catch(error => dispatch(throwError(error)));
 };

complex action creator

API request

import { CALL_API } from `redux-api-middleware`;

{
  [CALL_API]: {
    endpoint: 'api/account',
    method: 'GET',
    types: ['REQUEST', 'SUCCESS', 'FAILURE']
  }
}

action creators

SIDE EFFECTS - LESS BOILERPLATE

declarative

SIDE EFFECTS - LESS BOILERPLATE

chapter 2

PRODUCTION

FEATURE FOLDERS

FEATURE FOLDERS

view

actions

reducers

i

i

i

feature1

feature2

feature3

FEATURE FOLDERS

view

actions

reducers

i

i

i

feature1

feature2

feature3

set of standart components

FEATURE FOLDERS

view

actions

reducers

i

i

i

feature1

feature2

feature3

set of standart components

main reducer

FEATURE FOLDERS

view

actions

reducers

i

i

i

feature1

feature2

feature3

set of standart components

main reducer

all actions

FEATURE FOLDERS

our solutions

import reducers from './features/**/reducers.js';
yo redux-component
import actions from './features/**/actions.js';
account/
  Account.jsx
  actions.js
  reducres.js
button/
  Button.jsx
  b-button.scss

Smart (feature)

Dump

- if it receives a promise, it will dispatch the resolved           value of the promise

export function getAccount() {
  return async (api) => {
    return {
      type: events.ACCOUNT_READY,
      account: await api.options.account.get()
    };
  };
}

our case with ES7

SIDE EFFECTS - ADVANCED USAGE

Action Creator

Service 1

Service 2

Service 3

A

A

A

SIDE EFFECTS - ADVANCED USAGE

Action Creator

Service 1

Service 2

Service 3

A

A

A

SIDE EFFECTS - ADVANCED USAGE

Action Creator

Action Creator

SIDE EFFECTS - ADVANCED USAGE

applyMiddlewares(middleware1, middleware2, ...)
dispatch([
    startProcessCard(),
    setCreditCard(card),
    getOffers(),
    buy(plan.get('id')),
    pushState(null, '/account', {})
  ]);

async waterfall

SIDE EFFECTS - ADVANCED USAGE

chapter 3

SAGA

SAGA

orchestrating complex/asynchronous operations

Saga

Service 1

Service 2

Service 3

REDUX-SAGA

Generator functions (ES6) as action creators

1

function* fetchAccount() {
  const account = yield Api.fetch('/account')
  console.log(account)
}
function* watchFetchAccount() {
  yield* takeEvery('ACCOUNT_REQUESTED', fetchAccount)
}

REDUX-SAGA

Declarative Effects

{
  CALL: {
    fn: Api.fetch,
    args: ['./account']  
  }
}

2

yield only a description of

the function invocation

import { call } from 'redux-saga/effects'

function* fetchAccount() {
  const account = yield call(Api.fetch, '/account')
  // ...
}

- making our code testable

REDUX-SAGA

Dispatching actions

import { call } from 'redux-saga/effects'

function* fetchAccount(dispatch) {
  const account = yield call(Api.fetch, '/account')
  dispatch({ type: 'ACCOUNT_RECEIVED', account })
}
import { call, put } from 'redux-saga/effects'

function* fetchAccount() {
  const account = yield call(Api.fetch, '/account')
  yield put({ type: 'ACCOUNT_RECEIVED', products })
}

REDUX-SAGA

Testing

const iterator = fetchAccount()
assert.deepEqual(
  iterator.next().value,
  call(Api.fetch, '/account')
)
// create a fake response
const account = { balance: 10 }

// expects a dispatch instruction
assert.deepEqual(
  iterator.next(account).value,
  put({ type: 'ACCOUNT_RECEIVED', account })
)}

REDUX-SAGA API

takeEvery

takeLatest

Saga

take

put

call

A

Api

Dispatcher

fork

Saga

cancel

CONCLUSION

flux

redux

redux:

(state, action) => state 

CONCLUSION

flux

redux

redux:

(state, action) => state 

use feature folders

create collection of Dumb components

side-effects:

easy

complex

redux-thunk

redux-promise

redux-saga

i

THANK YOU FOR YOUR ATTENTION

Ievgen Terpil

Vyacheslav Pytel

Redux. From twitter hype to production

By Jenya Terpil

Redux. From twitter hype to production

  • 64,327