SlideShare ist ein Scribd-Unternehmen logo
1 von 49
Downloaden Sie, um offline zu lesen
React + Redux
Best practices
Борис Стринжа
Front-End Developer в Clickky
1. Create-react-app tool
1. Smart and Dumb components
2. Stateful and Stateless components
3. Binding
4. ShouldComponentUpdate
5. propTypes
6. Ducks pattern
7. Memoization (reselect)
8. Middlewares
React + Redux. Best practices
План
Почему мы используем
React?
React + Redux. Best practices
React + Redux. Best practices
Create React apps with no build configuration.
npm install -g create-react-app
create-react-app my-app
cd my-app/
npm start
React + Redux. Best practices
React + Redux. Best practices
To get started, edit src/App.js and save to reload
React + Redux. Best practices
package.json
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^15.4.2",
"react-dom": "^15.4.2"
},
"devDependencies": {
"react-scripts": "0.9.5"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
React + Redux. Best practices
npm run eject
Note: this is a one-way operation. Once you eject,
you can’t go back!
React + Redux. Best practices
Smart and Dumb
components
пример Dumb component
React + Redux. Best practices
пример Smart component
React + Redux. Best practices
Dumb
import React from 'react';
export default class Dumb extends React.Component {
selectNotificationItem = () => {
const {id} = this.props;
this.props.selectItem(id);
}
render () {
const {text, time} = this.props;
return (
<div className="item">
<span className="item__time">{time}</span>
<p className="item__text" onClick={this.selectNotificationItem}>{text}</p>
</div>
);
}
}
React + Redux. Best practices
<div className="list">
{list.map(item => {
return (
<Dumb
key={item.id}
id={item.id}
time={item.time}
text={item.text}
selectItem={this.handleSelectItem}
/>
);
})}
</div>
List.js
React + Redux. Best practices
Smartimport React from 'react';
import {connect} from 'react-redux';
import './App.css';
import Dumb from 'components/Dumb';
import {getNotificationsList, selectItem} from 'actions/notificatios';
class App extends React.Component {
componentWillMount() {
this.props.getNotificationsList();
}
handleSelectItem = (id) => {
this.props.selectItem(id);
}
render() {
const {list} = this.props;
return (
<div className="list">
{list.map(item => {
return (
<Dumb key={item.id} id={item.id} time={item.time} text={item.text} selectItem={this.handleSelectItem} />
);
})}
</div>
);
}
}
const mapStateToProps = (state) => ({
list:state.notifications.list
});
export default connect(mapStateToProps, {
getNotificationsList,
selectItem
})(App);
React + Redux. Best practices
Глупые компоненты:
1. Не зависят от остальной части приложения, например от redux actions или stores
2. Получают данные и колбэки исключительно через props
3. Имеют свой css файл
4. Изредка имеют свой state
5. Могут использовать другие глупые компоненты
Умные компоненты:
1. Оборачивает один или несколько глупых или умных компонентов
2. Хранит состояние стора и пробрасывает его как объекты в глупые компоненты
3. Вызывает redux actions и обеспечивает ими глупые компоненты в виде колбэков
4. Никогда не имеют собственных стилей
5. Редко сами выдают DOM, используйте глупые компоненты для макета
React + Redux. Best practices
Stateful and Stateless
components
React + Redux. Best practices
Stateful
import React from 'react';
export default class Counter extends React.Component {
state = {
count: 1
};
componentWillMount() {
this.setState({
count: this.state.count + 1
});
}
render () {
const {count} = this.state;
const {text} = this.props;
return (
<div className="item">
<span className="item__count">{count}</span>
<p className="item__text">{text}</p>
</div>
);
}
}
React + Redux. Best practices
Stateless
import React from 'react';
const Counter = ({addCount, text, count}) => {
return (
<div className="item">
<span className="item__count" onClick={addCount}>
{count}
</span>
<p className="item__text">{text}</p>
</div>
);
}
export default Counter;
React + Redux. Best practices
Binding
React + Redux. Best practices
Bind in Render
handleSelectItem(id) {
this.props.selectItem(id);
}
render() {
const {list} = this.props;
return (
<div className="list">
{list.map(item => {
return (
<div className="list__item" onClick={this.handleSelectItem.bind(this, item.id)}>
{item.text}
</div>
);
})}
</div>
);
}
handleSelectItem(id) {
this.props.selectItem(id);
}
render() {
const {list} = this.props;
return (
<div className="list">
{list.map(item => {
return (
<div className="list__item" onClick={(item) => this.handleSelectItem(item.id)}>
{item.text}
</div>
);
})}
</div>
);
}
React + Redux. Best practices
Arrow Function in Render
Bind in Constructor
constructor(props) {
super(props);
this.handleSelectItem = this.handleSelectItem.bind(this);
}
handleSelectItem(id) {
this.props.selectItem(id);
}
render() {
const {list} = this.props;
return (
<div className="list">
{list.map(item => {
return (
<div key={item.id} className="list__item">
<Dumb
id={item.id}
text={item.text}
selectItem={this.handleSelectItem}
/>
</div>
);
})}
</div>
);
}
React + Redux. Best practices
Arrow Function in Class Property
handleSelectItem = (id) => {
this.props.selectItem(id);
}
render() {
const {list} = this.props;
return (
<div className="list">
{list.map(item => {
return (
<div key={item.id} className="list__item">
<Dumb
id={item.id}
text={item.text}
selectItem={this.handleSelectItem}
/>
</div>
);
})}
</div>
);
}
React + Redux. Best practices
shouldComponentUpdate
React + Redux. Best practices
shouldComponentUpdate(nextProps, nextState) {
if (this.props.value !== nextProps.value) {
return true;
}
if (this.state.count !== nextState.count) {
return true;
}
return false;
}
component
React + Redux. Best practices
propTypes
export default class Activation extends React.Component {
static propTypes = {
query: React.PropTypes.object,
activatePublisher: React.PropTypes.func,
activateAdvertiser: React.PropTypes.func,
setActivationStatus: React.PropTypes.func,
isFetching: React.PropTypes.bool.isRequired,
activationStatus: React.PropTypes.bool.isRequired,
language: React.PropTypes.string
};
render() {
const {query} = this.props;
return(
<div></div>
);
}
}
components/Activation.js
React + Redux. Best practices
Console
React + Redux. Best practices
Ducks pattern
import {
NOTIFICATIONS_GET_LIST_REQUEST,
NOTIFICATIONS_GET_LIST_SUCCESS,
NOTIFICATIONS_GET_LIST_FAILURE,
NOTIFICATIONS_SELECT_ITEM
} from 'constants';
export function getNotificationsList() {
return {
types: [NOTIFICATIONS_GET_LIST_REQUEST, NOTIFICATIONS_GET_LIST_SUCCESS, NOTIFICATIONS_GET_LIST_FAILURE],
url: '/api/v1.0/notifications'
}
}
export function selectItem(data) {
return {
type: NOTIFICATIONS_SELECT_ITEM,
data
}
}
actions/notifications.js
React + Redux. Best practices
import {
NOTIFICATIONS_GET_LIST_REQUEST,
NOTIFICATIONS_GET_LIST_SUCCESS,
NOTIFICATIONS_GET_LIST_FAILURE,
NOTIFICATIONS_SELECT_ITEM
} from 'constants';
const initialState = {
list: [],
loading: false,
selected: null
};
export default (state = initialState, action = {}) => {
switch (action.type) {
case NOTIFICATIONS_GET_LIST_REQUEST:
return {
...state,
loading: true
};
case NOTIFICATIONS_GET_LIST_SUCCESS:
return {
...state,
list: actions.result,
loading: false
};
case NOTIFICATIONS_GET_LIST_FAILURE:
return {
...state,
loading: false
};
case NOTIFICATIONS_SELECT_ITEM:
return {
...state,
selected: action.data
};
default:
return state;
}
};
reducers/notifications.js
React + Redux. Best practices
export const NOTIFICATIONS_GET_LIST_REQUEST = 'NOTIFICATIONS_GET_LIST_REQUEST';
export const NOTIFICATIONS_GET_LIST_SUCCESS = 'NOTIFICATIONS_GET_LIST_SUCCESS';
export const NOTIFICATIONS_GET_LIST_FAILURE = 'NOTIFICATIONS_GET_LIST_FAILURE';
export const NOTIFICATIONS_SELECT_ITEM = 'NOTIFICATIONS_SELECT_ITEM';
constants/index.js
React + Redux. Best practices
// Actions
const GET_LIST_REQUEST = 'my-app/notifications/GET_LIST_REQUEST';
const GET_LIST_SUCCESS = 'my-app/notifications/GET_LIST_SUCCESS';
const GET_LIST_FAILURE = 'my-app/notifications/GET_LIST_FAILURE';
const SELECT_ITEM = 'my-app/notifications/SELECT_ITEM';
// Reducer
const initialState = {
list: [],
loading: false,
selected: null
};
export default function reducer(state = initialState, action = {}) => {
switch (action.type) {
case NOTIFICATIONS_GET_LIST_REQUEST:
return {
...state,
loading: true
};
case NOTIFICATIONS_GET_LIST_SUCCESS:
return {
...state,
list: actions.result,
loading: false
};
React + Redux. Best practices
modules/notifications.js
case NOTIFICATIONS_GET_LIST_FAILURE:
return {
...state,
loading: false
};
case NOTIFICATIONS_SELECT_ITEM:
return {
...state,
selected: action.data
};
default:
return state;
}
};
// Actions Creators
export function getNotificationsList() {
return {
types: [GET_LIST_REQUEST, GET_LIST_SUCCESS, GET_LIST_FAILURE],
url: '/api/v1.0/notifications'
}
}
export function selectItem(data) {
return {
type: SELECT_ITEM,
data
}
}
React + Redux. Best practices
1. MUST export default a function called reducer()
2. MUST export its action creators as functions
3. MUST have action types in the form
npm-module-or-app/reducer/ACTION_TYPE
4. MAY export its action types as UPPER_CASE, if an
external reducer needs to listen for them, or if it is a
published reusable library
React + Redux. Best practices
Requirements
Memoization
Memoization is an optimization technique used
primarily to speed up computer programs by storing
the results of expensive function calls and returning
the cached result when the same inputs occur again
React + Redux. Best practices
Reselect
import { createSelector } from 'reselect';
import {beautifyDate} from 'utils/date';
const data = (state) => state.notifications.data;
export const notificationsSelector = createSelector(
[data],
(notifications) => {
return notifications.reduce((list, item) => {
const title = beautifyDate(item.date, 'DD.MM.YYYY');
if (!list[title]) {
list[title] = [{...item}];
} else {
list[title] = [...list[title], {...item}];
}
return list;
}, {});
}
);
selectors/notifications.js
React + Redux. Best practices
import {notificationsSelector} from 'selectors/notifications';
const mapStateToProps = (state) => ({
list: notificationsSelector(state)
});
export default connect(mapStateToProps, {})(List);
containers/Notifications/index.js
React + Redux. Best practices
React + Redux. Best practices
Basic middleware
const customMiddleware = store => next => action => {
if (action.type !== 'custom') {
return next(action);
}
}
export default customMiddleware;
React + Redux. Best practices
store/index.js
import { createStore, applyMiddleware, } from 'redux'
import reducer from './reducer'
import customMiddleware from './customMiddleware'
const store = createStore(
reducer,
applyMiddleware(customMiddleware)
);
React + Redux. Best practices
middleware/apiMiddleware.js
import { push } from 'react-router-redux';
const apiMiddleware = (store) => (next) => (action) => {
const { url, types, method, body, ...rest } = action;
const { dispatch } = store;
if (!types) {
return next(action);
}
const [REQUEST, SUCCESS, FAILURE] = types;
next({...rest, type: REQUEST});
return fetch(url, {
method: method || 'GET',
credentials: 'same-origin',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(body)
}).then((res) => {
if (res.status >= 200 && res.status < 300) {
return res.json();
} else {
next({...rest, error: res.statusText, type: FAILURE});
if (res.status === 401) {
window.localStorage.removeItem('user');
dispatch(push('/login'));
}
return Promise.reject(new Error(res.statusText));
}
}).then(({result, ...rest}) => {
next({...rest, result, type: SUCCESS});
});
};
export default apiMiddleware;
export function getNotificationsList(data) {
return {
types: [NOTIFICATIONS_GET_LIST_REQUEST, NOTIFICATIONS_GET_LIST_SUCCESS,
NOTIFICATIONS_GET_LIST_FAILURE],
url: '/api/v1.0/notifications',
method: POST
body: data
}
}
actions/notifications.js
React + Redux. Best practices
Делаем небольшие dumb компоненты, не боимся использовать
connect, в пользу читаемости кода
Для простого рендера используем stateless компоненты
Всегда используем propTypes
Контролируем перерендер с помощью shouldComponentUpdate
Используем мемоизацию с помощью reselect
Используем middleware
Выводы
React + Redux. Best practices
Вопросы
49

Weitere ähnliche Inhalte

Was ist angesagt?

Was ist angesagt? (20)

Introduction to Redux
Introduction to ReduxIntroduction to Redux
Introduction to Redux
 
What is component in reactjs
What is component in reactjsWhat is component in reactjs
What is component in reactjs
 
A Brief Introduction to React.js
A Brief Introduction to React.jsA Brief Introduction to React.js
A Brief Introduction to React.js
 
Introduction to React JS
Introduction to React JSIntroduction to React JS
Introduction to React JS
 
React js programming concept
React js programming conceptReact js programming concept
React js programming concept
 
React workshop presentation
React workshop presentationReact workshop presentation
React workshop presentation
 
ReactJS
ReactJSReactJS
ReactJS
 
Redux workshop
Redux workshopRedux workshop
Redux workshop
 
React
React React
React
 
Reactjs
Reactjs Reactjs
Reactjs
 
Introduction to react_js
Introduction to react_jsIntroduction to react_js
Introduction to react_js
 
Ngrx slides
Ngrx slidesNgrx slides
Ngrx slides
 
reactJS
reactJSreactJS
reactJS
 
Understanding react hooks
Understanding react hooksUnderstanding react hooks
Understanding react hooks
 
React and redux
React and reduxReact and redux
React and redux
 
React + Redux + TypeScript === ♥
React + Redux + TypeScript === ♥React + Redux + TypeScript === ♥
React + Redux + TypeScript === ♥
 
React workshop
React workshopReact workshop
React workshop
 
An Introduction to Redux
An Introduction to ReduxAn Introduction to Redux
An Introduction to Redux
 
Redux Toolkit - Quick Intro - 2022
Redux Toolkit - Quick Intro - 2022Redux Toolkit - Quick Intro - 2022
Redux Toolkit - Quick Intro - 2022
 
React js for beginners
React js for beginnersReact js for beginners
React js for beginners
 

Ähnlich wie React + Redux. Best practices

Integrating React.js with PHP projects
Integrating React.js with PHP projectsIntegrating React.js with PHP projects
Integrating React.js with PHP projectsIgnacio Martín
 
Intro to React | DreamLab Academy
Intro to React | DreamLab AcademyIntro to React | DreamLab Academy
Intro to React | DreamLab AcademyDreamLab
 
React, Redux and es6/7
React, Redux and es6/7React, Redux and es6/7
React, Redux and es6/7Dongho Cho
 
Intro to Redux | DreamLab Academy #3
Intro to Redux | DreamLab Academy #3 Intro to Redux | DreamLab Academy #3
Intro to Redux | DreamLab Academy #3 DreamLab
 
Battle of React State Managers in frontend applications
Battle of React State Managers in frontend applicationsBattle of React State Managers in frontend applications
Battle of React State Managers in frontend applicationsEvangelia Mitsopoulou
 
Reactивная тяга
Reactивная тягаReactивная тяга
Reactивная тягаVitebsk Miniq
 
Workshop 20: ReactJS Part II Flux Pattern & Redux
Workshop 20: ReactJS Part II Flux Pattern & ReduxWorkshop 20: ReactJS Part II Flux Pattern & Redux
Workshop 20: ReactJS Part II Flux Pattern & ReduxVisual Engineering
 
Using React, Redux and Saga with Lottoland APIs
Using React, Redux and Saga with Lottoland APIsUsing React, Redux and Saga with Lottoland APIs
Using React, Redux and Saga with Lottoland APIsMihail Gaberov
 
Introducing Vuex in your project
Introducing Vuex in your projectIntroducing Vuex in your project
Introducing Vuex in your projectDenny Biasiolli
 
State manager in Vue.js, from zero to Vuex
State manager in Vue.js, from zero to VuexState manager in Vue.js, from zero to Vuex
State manager in Vue.js, from zero to VuexCommit University
 
EWD 3 Training Course Part 39: Building a React.js application with QEWD, Part 3
EWD 3 Training Course Part 39: Building a React.js application with QEWD, Part 3EWD 3 Training Course Part 39: Building a React.js application with QEWD, Part 3
EWD 3 Training Course Part 39: Building a React.js application with QEWD, Part 3Rob Tweed
 
MeetJS Summit 2016: React.js enlightenment
MeetJS Summit 2016: React.js enlightenmentMeetJS Summit 2016: React.js enlightenment
MeetJS Summit 2016: React.js enlightenmentArtur Szott
 
Recompacting your react application
Recompacting your react applicationRecompacting your react application
Recompacting your react applicationGreg Bergé
 
Reactive.architecture.with.Angular
Reactive.architecture.with.AngularReactive.architecture.with.Angular
Reactive.architecture.with.AngularEvan Schultz
 
Server side rendering with React and Symfony
Server side rendering with React and SymfonyServer side rendering with React and Symfony
Server side rendering with React and SymfonyIgnacio Martín
 
JS Fest 2019. Glenn Reyes. With great power comes great React hooks!
JS Fest 2019. Glenn Reyes. With great power comes great React hooks!JS Fest 2019. Glenn Reyes. With great power comes great React hooks!
JS Fest 2019. Glenn Reyes. With great power comes great React hooks!JSFestUA
 
Workshop 19: ReactJS Introduction
Workshop 19: ReactJS IntroductionWorkshop 19: ReactJS Introduction
Workshop 19: ReactJS IntroductionVisual Engineering
 
[Final] ReactJS presentation
[Final] ReactJS presentation[Final] ReactJS presentation
[Final] ReactJS presentation洪 鹏发
 

Ähnlich wie React + Redux. Best practices (20)

React lecture
React lectureReact lecture
React lecture
 
Integrating React.js with PHP projects
Integrating React.js with PHP projectsIntegrating React.js with PHP projects
Integrating React.js with PHP projects
 
Intro to React | DreamLab Academy
Intro to React | DreamLab AcademyIntro to React | DreamLab Academy
Intro to React | DreamLab Academy
 
React redux
React reduxReact redux
React redux
 
React, Redux and es6/7
React, Redux and es6/7React, Redux and es6/7
React, Redux and es6/7
 
Intro to Redux | DreamLab Academy #3
Intro to Redux | DreamLab Academy #3 Intro to Redux | DreamLab Academy #3
Intro to Redux | DreamLab Academy #3
 
Battle of React State Managers in frontend applications
Battle of React State Managers in frontend applicationsBattle of React State Managers in frontend applications
Battle of React State Managers in frontend applications
 
Reactивная тяга
Reactивная тягаReactивная тяга
Reactивная тяга
 
Workshop 20: ReactJS Part II Flux Pattern & Redux
Workshop 20: ReactJS Part II Flux Pattern & ReduxWorkshop 20: ReactJS Part II Flux Pattern & Redux
Workshop 20: ReactJS Part II Flux Pattern & Redux
 
Using React, Redux and Saga with Lottoland APIs
Using React, Redux and Saga with Lottoland APIsUsing React, Redux and Saga with Lottoland APIs
Using React, Redux and Saga with Lottoland APIs
 
Introducing Vuex in your project
Introducing Vuex in your projectIntroducing Vuex in your project
Introducing Vuex in your project
 
State manager in Vue.js, from zero to Vuex
State manager in Vue.js, from zero to VuexState manager in Vue.js, from zero to Vuex
State manager in Vue.js, from zero to Vuex
 
EWD 3 Training Course Part 39: Building a React.js application with QEWD, Part 3
EWD 3 Training Course Part 39: Building a React.js application with QEWD, Part 3EWD 3 Training Course Part 39: Building a React.js application with QEWD, Part 3
EWD 3 Training Course Part 39: Building a React.js application with QEWD, Part 3
 
MeetJS Summit 2016: React.js enlightenment
MeetJS Summit 2016: React.js enlightenmentMeetJS Summit 2016: React.js enlightenment
MeetJS Summit 2016: React.js enlightenment
 
Recompacting your react application
Recompacting your react applicationRecompacting your react application
Recompacting your react application
 
Reactive.architecture.with.Angular
Reactive.architecture.with.AngularReactive.architecture.with.Angular
Reactive.architecture.with.Angular
 
Server side rendering with React and Symfony
Server side rendering with React and SymfonyServer side rendering with React and Symfony
Server side rendering with React and Symfony
 
JS Fest 2019. Glenn Reyes. With great power comes great React hooks!
JS Fest 2019. Glenn Reyes. With great power comes great React hooks!JS Fest 2019. Glenn Reyes. With great power comes great React hooks!
JS Fest 2019. Glenn Reyes. With great power comes great React hooks!
 
Workshop 19: ReactJS Introduction
Workshop 19: ReactJS IntroductionWorkshop 19: ReactJS Introduction
Workshop 19: ReactJS Introduction
 
[Final] ReactJS presentation
[Final] ReactJS presentation[Final] ReactJS presentation
[Final] ReactJS presentation
 

Mehr von Clickky

Case-study: How to market ICO with success.
Case-study: How to market ICO with success. Case-study: How to market ICO with success.
Case-study: How to market ICO with success. Clickky
 
Clickhouse
ClickhouseClickhouse
ClickhouseClickky
 
Лучшие кейсы и практики монетизации мобильного трафика
Лучшие кейсы и практики монетизации мобильного трафикаЛучшие кейсы и практики монетизации мобильного трафика
Лучшие кейсы и практики монетизации мобильного трафикаClickky
 
Case study. Advertisers success in mobile economy
Case study. Advertisers success in mobile economyCase study. Advertisers success in mobile economy
Case study. Advertisers success in mobile economyClickky
 
#MBC2016 Dan Ekstein, Supersonic Finding the Perfect Balance Between Rewarded...
#MBC2016 Dan Ekstein, Supersonic Finding the Perfect Balance Between Rewarded...#MBC2016 Dan Ekstein, Supersonic Finding the Perfect Balance Between Rewarded...
#MBC2016 Dan Ekstein, Supersonic Finding the Perfect Balance Between Rewarded...Clickky
 
#MBC2016 Кирилл Софронов, Remerge: Ретаргетинг в мобильных приложениях: опыт ...
#MBC2016 Кирилл Софронов, Remerge: Ретаргетинг в мобильных приложениях: опыт ...#MBC2016 Кирилл Софронов, Remerge: Ретаргетинг в мобильных приложениях: опыт ...
#MBC2016 Кирилл Софронов, Remerge: Ретаргетинг в мобильных приложениях: опыт ...Clickky
 
#MBC2016 Илья Лагутин, Aitarget: Как эффективно продвигать мобильные приложен...
#MBC2016 Илья Лагутин, Aitarget: Как эффективно продвигать мобильные приложен...#MBC2016 Илья Лагутин, Aitarget: Как эффективно продвигать мобильные приложен...
#MBC2016 Илья Лагутин, Aitarget: Как эффективно продвигать мобильные приложен...Clickky
 
#MBC2016 Mark Ten, Sports.ru: Programmatic monetization of mobile apps
#MBC2016 Mark Ten, Sports.ru: Programmatic monetization of mobile apps#MBC2016 Mark Ten, Sports.ru: Programmatic monetization of mobile apps
#MBC2016 Mark Ten, Sports.ru: Programmatic monetization of mobile appsClickky
 
#MBC2016 Dvir Doron, Cedato: Mobile video - the new growth engine
#MBC2016 Dvir Doron, Cedato: Mobile video - the new growth engine #MBC2016 Dvir Doron, Cedato: Mobile video - the new growth engine
#MBC2016 Dvir Doron, Cedato: Mobile video - the new growth engine Clickky
 
#MBC2016 Bashir Modanov, NewBornTown: Globalized mobile ecosystem
#MBC2016 Bashir Modanov, NewBornTown: Globalized mobile ecosystem#MBC2016 Bashir Modanov, NewBornTown: Globalized mobile ecosystem
#MBC2016 Bashir Modanov, NewBornTown: Globalized mobile ecosystemClickky
 
Как настроить B2B продажи за границей из Украины
Как настроить B2B продажи за границей из УкраиныКак настроить B2B продажи за границей из Украины
Как настроить B2B продажи за границей из УкраиныClickky
 
Как выжать еще больше из мобильного трафика?
Как выжать еще больше из мобильного трафика?Как выжать еще больше из мобильного трафика?
Как выжать еще больше из мобильного трафика?Clickky
 
AdExchange mediakit
AdExchange mediakitAdExchange mediakit
AdExchange mediakitClickky
 
Поймай меня, если сможешь
Поймай меня, если сможешьПоймай меня, если сможешь
Поймай меня, если сможешьClickky
 
WannaBiz Fund
WannaBiz FundWannaBiz Fund
WannaBiz FundClickky
 
AdExchange mediakit
AdExchange mediakitAdExchange mediakit
AdExchange mediakitClickky
 
Clickky fraud presentation at Kinza 2015
Clickky fraud presentation at Kinza 2015Clickky fraud presentation at Kinza 2015
Clickky fraud presentation at Kinza 2015Clickky
 
МАРКЕТИНГОВЫЕ ЦЕЛИ И ЗАКУПКА ТРАФИКА
МАРКЕТИНГОВЫЕ ЦЕЛИ И ЗАКУПКА ТРАФИКАМАРКЕТИНГОВЫЕ ЦЕЛИ И ЗАКУПКА ТРАФИКА
МАРКЕТИНГОВЫЕ ЦЕЛИ И ЗАКУПКА ТРАФИКАClickky
 
The trends of mobile in e-commerce, Mobilimes Serg Korneev
The trends of mobile in e-commerce, Mobilimes Serg KorneevThe trends of mobile in e-commerce, Mobilimes Serg Korneev
The trends of mobile in e-commerce, Mobilimes Serg KorneevClickky
 
Инвестиции в mobile marketing, Алексей Тельнов iTech Capital, Mobile Beach Co...
Инвестиции в mobile marketing, Алексей Тельнов iTech Capital, Mobile Beach Co...Инвестиции в mobile marketing, Алексей Тельнов iTech Capital, Mobile Beach Co...
Инвестиции в mobile marketing, Алексей Тельнов iTech Capital, Mobile Beach Co...Clickky
 

Mehr von Clickky (20)

Case-study: How to market ICO with success.
Case-study: How to market ICO with success. Case-study: How to market ICO with success.
Case-study: How to market ICO with success.
 
Clickhouse
ClickhouseClickhouse
Clickhouse
 
Лучшие кейсы и практики монетизации мобильного трафика
Лучшие кейсы и практики монетизации мобильного трафикаЛучшие кейсы и практики монетизации мобильного трафика
Лучшие кейсы и практики монетизации мобильного трафика
 
Case study. Advertisers success in mobile economy
Case study. Advertisers success in mobile economyCase study. Advertisers success in mobile economy
Case study. Advertisers success in mobile economy
 
#MBC2016 Dan Ekstein, Supersonic Finding the Perfect Balance Between Rewarded...
#MBC2016 Dan Ekstein, Supersonic Finding the Perfect Balance Between Rewarded...#MBC2016 Dan Ekstein, Supersonic Finding the Perfect Balance Between Rewarded...
#MBC2016 Dan Ekstein, Supersonic Finding the Perfect Balance Between Rewarded...
 
#MBC2016 Кирилл Софронов, Remerge: Ретаргетинг в мобильных приложениях: опыт ...
#MBC2016 Кирилл Софронов, Remerge: Ретаргетинг в мобильных приложениях: опыт ...#MBC2016 Кирилл Софронов, Remerge: Ретаргетинг в мобильных приложениях: опыт ...
#MBC2016 Кирилл Софронов, Remerge: Ретаргетинг в мобильных приложениях: опыт ...
 
#MBC2016 Илья Лагутин, Aitarget: Как эффективно продвигать мобильные приложен...
#MBC2016 Илья Лагутин, Aitarget: Как эффективно продвигать мобильные приложен...#MBC2016 Илья Лагутин, Aitarget: Как эффективно продвигать мобильные приложен...
#MBC2016 Илья Лагутин, Aitarget: Как эффективно продвигать мобильные приложен...
 
#MBC2016 Mark Ten, Sports.ru: Programmatic monetization of mobile apps
#MBC2016 Mark Ten, Sports.ru: Programmatic monetization of mobile apps#MBC2016 Mark Ten, Sports.ru: Programmatic monetization of mobile apps
#MBC2016 Mark Ten, Sports.ru: Programmatic monetization of mobile apps
 
#MBC2016 Dvir Doron, Cedato: Mobile video - the new growth engine
#MBC2016 Dvir Doron, Cedato: Mobile video - the new growth engine #MBC2016 Dvir Doron, Cedato: Mobile video - the new growth engine
#MBC2016 Dvir Doron, Cedato: Mobile video - the new growth engine
 
#MBC2016 Bashir Modanov, NewBornTown: Globalized mobile ecosystem
#MBC2016 Bashir Modanov, NewBornTown: Globalized mobile ecosystem#MBC2016 Bashir Modanov, NewBornTown: Globalized mobile ecosystem
#MBC2016 Bashir Modanov, NewBornTown: Globalized mobile ecosystem
 
Как настроить B2B продажи за границей из Украины
Как настроить B2B продажи за границей из УкраиныКак настроить B2B продажи за границей из Украины
Как настроить B2B продажи за границей из Украины
 
Как выжать еще больше из мобильного трафика?
Как выжать еще больше из мобильного трафика?Как выжать еще больше из мобильного трафика?
Как выжать еще больше из мобильного трафика?
 
AdExchange mediakit
AdExchange mediakitAdExchange mediakit
AdExchange mediakit
 
Поймай меня, если сможешь
Поймай меня, если сможешьПоймай меня, если сможешь
Поймай меня, если сможешь
 
WannaBiz Fund
WannaBiz FundWannaBiz Fund
WannaBiz Fund
 
AdExchange mediakit
AdExchange mediakitAdExchange mediakit
AdExchange mediakit
 
Clickky fraud presentation at Kinza 2015
Clickky fraud presentation at Kinza 2015Clickky fraud presentation at Kinza 2015
Clickky fraud presentation at Kinza 2015
 
МАРКЕТИНГОВЫЕ ЦЕЛИ И ЗАКУПКА ТРАФИКА
МАРКЕТИНГОВЫЕ ЦЕЛИ И ЗАКУПКА ТРАФИКАМАРКЕТИНГОВЫЕ ЦЕЛИ И ЗАКУПКА ТРАФИКА
МАРКЕТИНГОВЫЕ ЦЕЛИ И ЗАКУПКА ТРАФИКА
 
The trends of mobile in e-commerce, Mobilimes Serg Korneev
The trends of mobile in e-commerce, Mobilimes Serg KorneevThe trends of mobile in e-commerce, Mobilimes Serg Korneev
The trends of mobile in e-commerce, Mobilimes Serg Korneev
 
Инвестиции в mobile marketing, Алексей Тельнов iTech Capital, Mobile Beach Co...
Инвестиции в mobile marketing, Алексей Тельнов iTech Capital, Mobile Beach Co...Инвестиции в mobile marketing, Алексей Тельнов iTech Capital, Mobile Beach Co...
Инвестиции в mobile marketing, Алексей Тельнов iTech Capital, Mobile Beach Co...
 

Kürzlich hochgeladen

Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AIABDERRAOUF MEHENNI
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
Clustering techniques data mining book ....
Clustering techniques data mining book ....Clustering techniques data mining book ....
Clustering techniques data mining book ....ShaimaaMohamedGalal
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfCionsystems
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 

Kürzlich hochgeladen (20)

Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
Clustering techniques data mining book ....
Clustering techniques data mining book ....Clustering techniques data mining book ....
Clustering techniques data mining book ....
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdf
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 

React + Redux. Best practices

  • 1. React + Redux Best practices
  • 3. 1. Create-react-app tool 1. Smart and Dumb components 2. Stateful and Stateless components 3. Binding 4. ShouldComponentUpdate 5. propTypes 6. Ducks pattern 7. Memoization (reselect) 8. Middlewares React + Redux. Best practices План
  • 5. React + Redux. Best practices
  • 6. Create React apps with no build configuration. npm install -g create-react-app create-react-app my-app cd my-app/ npm start React + Redux. Best practices
  • 7. React + Redux. Best practices
  • 8. To get started, edit src/App.js and save to reload React + Redux. Best practices
  • 9. package.json { "name": "my-app", "version": "0.1.0", "private": true, "dependencies": { "react": "^15.4.2", "react-dom": "^15.4.2" }, "devDependencies": { "react-scripts": "0.9.5" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" } } React + Redux. Best practices
  • 10. npm run eject Note: this is a one-way operation. Once you eject, you can’t go back! React + Redux. Best practices
  • 12. пример Dumb component React + Redux. Best practices
  • 13. пример Smart component React + Redux. Best practices
  • 14. Dumb import React from 'react'; export default class Dumb extends React.Component { selectNotificationItem = () => { const {id} = this.props; this.props.selectItem(id); } render () { const {text, time} = this.props; return ( <div className="item"> <span className="item__time">{time}</span> <p className="item__text" onClick={this.selectNotificationItem}>{text}</p> </div> ); } } React + Redux. Best practices
  • 15. <div className="list"> {list.map(item => { return ( <Dumb key={item.id} id={item.id} time={item.time} text={item.text} selectItem={this.handleSelectItem} /> ); })} </div> List.js React + Redux. Best practices
  • 16. Smartimport React from 'react'; import {connect} from 'react-redux'; import './App.css'; import Dumb from 'components/Dumb'; import {getNotificationsList, selectItem} from 'actions/notificatios'; class App extends React.Component { componentWillMount() { this.props.getNotificationsList(); } handleSelectItem = (id) => { this.props.selectItem(id); } render() { const {list} = this.props; return ( <div className="list"> {list.map(item => { return ( <Dumb key={item.id} id={item.id} time={item.time} text={item.text} selectItem={this.handleSelectItem} /> ); })} </div> ); } } const mapStateToProps = (state) => ({ list:state.notifications.list }); export default connect(mapStateToProps, { getNotificationsList, selectItem })(App); React + Redux. Best practices
  • 17. Глупые компоненты: 1. Не зависят от остальной части приложения, например от redux actions или stores 2. Получают данные и колбэки исключительно через props 3. Имеют свой css файл 4. Изредка имеют свой state 5. Могут использовать другие глупые компоненты Умные компоненты: 1. Оборачивает один или несколько глупых или умных компонентов 2. Хранит состояние стора и пробрасывает его как объекты в глупые компоненты 3. Вызывает redux actions и обеспечивает ими глупые компоненты в виде колбэков 4. Никогда не имеют собственных стилей 5. Редко сами выдают DOM, используйте глупые компоненты для макета React + Redux. Best practices
  • 18. Stateful and Stateless components React + Redux. Best practices
  • 19. Stateful import React from 'react'; export default class Counter extends React.Component { state = { count: 1 }; componentWillMount() { this.setState({ count: this.state.count + 1 }); } render () { const {count} = this.state; const {text} = this.props; return ( <div className="item"> <span className="item__count">{count}</span> <p className="item__text">{text}</p> </div> ); } } React + Redux. Best practices
  • 20. Stateless import React from 'react'; const Counter = ({addCount, text, count}) => { return ( <div className="item"> <span className="item__count" onClick={addCount}> {count} </span> <p className="item__text">{text}</p> </div> ); } export default Counter; React + Redux. Best practices
  • 22. React + Redux. Best practices Bind in Render handleSelectItem(id) { this.props.selectItem(id); } render() { const {list} = this.props; return ( <div className="list"> {list.map(item => { return ( <div className="list__item" onClick={this.handleSelectItem.bind(this, item.id)}> {item.text} </div> ); })} </div> ); }
  • 23. handleSelectItem(id) { this.props.selectItem(id); } render() { const {list} = this.props; return ( <div className="list"> {list.map(item => { return ( <div className="list__item" onClick={(item) => this.handleSelectItem(item.id)}> {item.text} </div> ); })} </div> ); } React + Redux. Best practices Arrow Function in Render
  • 24. Bind in Constructor constructor(props) { super(props); this.handleSelectItem = this.handleSelectItem.bind(this); } handleSelectItem(id) { this.props.selectItem(id); } render() { const {list} = this.props; return ( <div className="list"> {list.map(item => { return ( <div key={item.id} className="list__item"> <Dumb id={item.id} text={item.text} selectItem={this.handleSelectItem} /> </div> ); })} </div> ); } React + Redux. Best practices
  • 25. Arrow Function in Class Property handleSelectItem = (id) => { this.props.selectItem(id); } render() { const {list} = this.props; return ( <div className="list"> {list.map(item => { return ( <div key={item.id} className="list__item"> <Dumb id={item.id} text={item.text} selectItem={this.handleSelectItem} /> </div> ); })} </div> ); } React + Redux. Best practices
  • 27. shouldComponentUpdate(nextProps, nextState) { if (this.props.value !== nextProps.value) { return true; } if (this.state.count !== nextState.count) { return true; } return false; } component React + Redux. Best practices
  • 29. export default class Activation extends React.Component { static propTypes = { query: React.PropTypes.object, activatePublisher: React.PropTypes.func, activateAdvertiser: React.PropTypes.func, setActivationStatus: React.PropTypes.func, isFetching: React.PropTypes.bool.isRequired, activationStatus: React.PropTypes.bool.isRequired, language: React.PropTypes.string }; render() { const {query} = this.props; return( <div></div> ); } } components/Activation.js React + Redux. Best practices
  • 30. Console React + Redux. Best practices
  • 32. import { NOTIFICATIONS_GET_LIST_REQUEST, NOTIFICATIONS_GET_LIST_SUCCESS, NOTIFICATIONS_GET_LIST_FAILURE, NOTIFICATIONS_SELECT_ITEM } from 'constants'; export function getNotificationsList() { return { types: [NOTIFICATIONS_GET_LIST_REQUEST, NOTIFICATIONS_GET_LIST_SUCCESS, NOTIFICATIONS_GET_LIST_FAILURE], url: '/api/v1.0/notifications' } } export function selectItem(data) { return { type: NOTIFICATIONS_SELECT_ITEM, data } } actions/notifications.js React + Redux. Best practices
  • 33. import { NOTIFICATIONS_GET_LIST_REQUEST, NOTIFICATIONS_GET_LIST_SUCCESS, NOTIFICATIONS_GET_LIST_FAILURE, NOTIFICATIONS_SELECT_ITEM } from 'constants'; const initialState = { list: [], loading: false, selected: null }; export default (state = initialState, action = {}) => { switch (action.type) { case NOTIFICATIONS_GET_LIST_REQUEST: return { ...state, loading: true }; case NOTIFICATIONS_GET_LIST_SUCCESS: return { ...state, list: actions.result, loading: false }; case NOTIFICATIONS_GET_LIST_FAILURE: return { ...state, loading: false }; case NOTIFICATIONS_SELECT_ITEM: return { ...state, selected: action.data }; default: return state; } }; reducers/notifications.js React + Redux. Best practices
  • 34. export const NOTIFICATIONS_GET_LIST_REQUEST = 'NOTIFICATIONS_GET_LIST_REQUEST'; export const NOTIFICATIONS_GET_LIST_SUCCESS = 'NOTIFICATIONS_GET_LIST_SUCCESS'; export const NOTIFICATIONS_GET_LIST_FAILURE = 'NOTIFICATIONS_GET_LIST_FAILURE'; export const NOTIFICATIONS_SELECT_ITEM = 'NOTIFICATIONS_SELECT_ITEM'; constants/index.js React + Redux. Best practices
  • 35. // Actions const GET_LIST_REQUEST = 'my-app/notifications/GET_LIST_REQUEST'; const GET_LIST_SUCCESS = 'my-app/notifications/GET_LIST_SUCCESS'; const GET_LIST_FAILURE = 'my-app/notifications/GET_LIST_FAILURE'; const SELECT_ITEM = 'my-app/notifications/SELECT_ITEM'; // Reducer const initialState = { list: [], loading: false, selected: null }; export default function reducer(state = initialState, action = {}) => { switch (action.type) { case NOTIFICATIONS_GET_LIST_REQUEST: return { ...state, loading: true }; case NOTIFICATIONS_GET_LIST_SUCCESS: return { ...state, list: actions.result, loading: false }; React + Redux. Best practices modules/notifications.js
  • 36. case NOTIFICATIONS_GET_LIST_FAILURE: return { ...state, loading: false }; case NOTIFICATIONS_SELECT_ITEM: return { ...state, selected: action.data }; default: return state; } }; // Actions Creators export function getNotificationsList() { return { types: [GET_LIST_REQUEST, GET_LIST_SUCCESS, GET_LIST_FAILURE], url: '/api/v1.0/notifications' } } export function selectItem(data) { return { type: SELECT_ITEM, data } } React + Redux. Best practices
  • 37. 1. MUST export default a function called reducer() 2. MUST export its action creators as functions 3. MUST have action types in the form npm-module-or-app/reducer/ACTION_TYPE 4. MAY export its action types as UPPER_CASE, if an external reducer needs to listen for them, or if it is a published reusable library React + Redux. Best practices Requirements
  • 39. Memoization is an optimization technique used primarily to speed up computer programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again React + Redux. Best practices
  • 41. import { createSelector } from 'reselect'; import {beautifyDate} from 'utils/date'; const data = (state) => state.notifications.data; export const notificationsSelector = createSelector( [data], (notifications) => { return notifications.reduce((list, item) => { const title = beautifyDate(item.date, 'DD.MM.YYYY'); if (!list[title]) { list[title] = [{...item}]; } else { list[title] = [...list[title], {...item}]; } return list; }, {}); } ); selectors/notifications.js React + Redux. Best practices
  • 42. import {notificationsSelector} from 'selectors/notifications'; const mapStateToProps = (state) => ({ list: notificationsSelector(state) }); export default connect(mapStateToProps, {})(List); containers/Notifications/index.js React + Redux. Best practices
  • 43. React + Redux. Best practices
  • 44. Basic middleware const customMiddleware = store => next => action => { if (action.type !== 'custom') { return next(action); } } export default customMiddleware; React + Redux. Best practices
  • 45. store/index.js import { createStore, applyMiddleware, } from 'redux' import reducer from './reducer' import customMiddleware from './customMiddleware' const store = createStore( reducer, applyMiddleware(customMiddleware) ); React + Redux. Best practices
  • 46. middleware/apiMiddleware.js import { push } from 'react-router-redux'; const apiMiddleware = (store) => (next) => (action) => { const { url, types, method, body, ...rest } = action; const { dispatch } = store; if (!types) { return next(action); } const [REQUEST, SUCCESS, FAILURE] = types; next({...rest, type: REQUEST}); return fetch(url, { method: method || 'GET', credentials: 'same-origin', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify(body) }).then((res) => { if (res.status >= 200 && res.status < 300) { return res.json(); } else { next({...rest, error: res.statusText, type: FAILURE}); if (res.status === 401) { window.localStorage.removeItem('user'); dispatch(push('/login')); } return Promise.reject(new Error(res.statusText)); } }).then(({result, ...rest}) => { next({...rest, result, type: SUCCESS}); }); }; export default apiMiddleware;
  • 47. export function getNotificationsList(data) { return { types: [NOTIFICATIONS_GET_LIST_REQUEST, NOTIFICATIONS_GET_LIST_SUCCESS, NOTIFICATIONS_GET_LIST_FAILURE], url: '/api/v1.0/notifications', method: POST body: data } } actions/notifications.js React + Redux. Best practices
  • 48. Делаем небольшие dumb компоненты, не боимся использовать connect, в пользу читаемости кода Для простого рендера используем stateless компоненты Всегда используем propTypes Контролируем перерендер с помощью shouldComponentUpdate Используем мемоизацию с помощью reselect Используем middleware Выводы React + Redux. Best practices