ݺߣ

ݺߣShare a Scribd company logo
Коротко о React.js
Автор: Александр Вишняков MadDevs
О чем поговорим
● React - почему он нужен?
● Flux Utils
● Redux
● Частые ошибки разработчиков
React - зачем он нужен?
● Гибкая архитектура
● Разделение ответственностей
● Легкое тестирование
● Переиспользование кода
Flux Utils
● Удобное создание Store с использованием
ReduceStore<T>
● Контейнеры Container.create()
○ Взаимодействует со всеми Store
○ Освобождает компонент от связности со Store,
оставляя только использование action’ов внутри
компонента
Redux
Redux Store
● Все состояния хранятся в едином сторе. Всего один стор на все
приложение.
● store.getState() - так получаем содержимое состояния Store
● Состояние нельзя изменять на прямую, минуя экшены.
● У Store как правило, нет публичных методов для изменения
состояния.
● Это чистая функция, которая обрабатывает экшены
Redux action
● Это обычно просто хеш объект, который отправляется через
dispatch({
type: ‘ACTION_TYPE_NAME’,
payload: {
…. // Данные экшена
},
meta: {
…. // Служебные данные экшна
}
})
Чистая функция
● Они зависят только от своих параметров. И возвращают только
свой результат.
● Не используют никакие глобальные переменные и не изменяют
состояние вне тела функции.
○ Math.sin(x)
○ parseInt(x, y)
○ $.ajax() - уже не чистая функция
Redux Reducer
function reducer(state, action) {
switch(action.type){
case ‘SOME_ACTION_TYPE’:
return {
alias: {
...state.alias,
...action.payload
}
}
default:
return state
}
}
Redux сайд-эффекты
● Сайд-эффект - это когда приходится изменять состояние
глобально, к примеру после обращения к API
● В классической схеме Flux паттерна, нет места таким
манипуляциям.
● Для обработки сайд-эффектов в Redux присутствует понятие
прослойки или Middleware
● Middleware - может быть много, по аналогии с веб
фреймворками (схема не нова)
Redux сайд-эффекты
Redux middleware
const logMiddleware =
store => next => action => {
console.log(action);
next(action);
}
const store = createStore(store)(reducer,
applyMiddleware(logMiddleware))
Redux-thunk
● Предоставляет возможность диспатчить функции вместо
традиционных объектов, как это принято в Redux.
● В переданной функции мы можем сделать вызов api, проделать
какие нибудь вычисления и вызвать dispatch в нужный для нас
момент.
store.dispatch((dispatch) => {
fetch(‘/api/some/data’).then(
data => dispatch(successAction(data)),
err => dispatch(failAction(err))
)
})
Redux-thunk
Import thunk from ‘redux-thunk’;
const store = createStore(reducer, applyMiddleware(thunk))
Redux thunk (пример)
const login = (user, password) => dispatch => {
const formData = new FormData();
formData.append(“user”, user)
formData.append(“password”, password)
fetch(‘/login’, { method: ‘POST’, data: formData }).then(
data => dispatch(loginSuccess(data)),
err => dispatch(loginFail(err)))
}
store.dispatch(login(‘user1’, ‘password1’))
Redux thunk (несколько экшенов за раз)
const someAction = () => (dispatch, state) => {
dispatch(someAction1(state.alias.field))
dispatch(someAction2())
}
store.dispatch(someAction())
Redux-saga
Сага - собирает всю логику обработки внутрь себя в отличии от thunk,
где приходится разбивать на мелкие функции и постоянно их
диспатчить.
В Saga - все асинхронное выполняется линейно благодаря function* в
купе с yeild
Redux-saga example
function* login(user, password) {
const formData = new FormData();
formData.append(“user”, user)
formData.append(“password”, password)
try {
const data = yield call(fetch, ‘/login’, { method: ‘POST’, data: formData })
yield put(dispatch(loginSuccess(data)))
} catch(e) {
yield put(dispatch(loginFail(e)))
}
}
Redux-saga (типы подписки при помощи
takeEvery)
function* processAction(api, { payload, meta }) { … }
function* subscribeForAction(api) {
yield* takeEvery(‘SOME_ACTION_1’, processAction, api)
}
Redux saga (подписка при помощи take и
while)
function* processAction(api, { data }, { resource, thunk }) {
try {
const detail = yield call([api, api.post], `/${resource}`, data)
yield put(actions.someSuccessAction(resource, detail, data, thunk))
} catch (e) {
yield put(actions.someFailAction(resource, e, data, thunk))
}
}
function* action1(api) {
while(true) {
const { payload, meta } = yield take(‘SOME_ACTION_1’, )
yield call(processAction(api, payload, meta))
}
}
Ошибки разработчиков
● Обертка в ( ) => { … } обработчиков события
<Component onClick={ (e) => someHandler(e) } />
Ошибки разработчиков
● Использование неправильных значений для свойства key={}
компонента
{ list.each((item, index) => {
<Component key={Math.random()} data={item}/>
// или
<Component key={index} data={item}/>
})
Ошибки разработчиков
● Рендер коллекции компонентов и хардкод передаваемых
данных в событии компонента.
○ Это неверное распределение обязанностей, возложенное
на родительский компонент
{
list.each((item, index) => {
<Component key={item.id} data={item}
onClick={(e) => onItemSelect(item)}/>
})
}

More Related Content

Коротко о React.js

  • 1. Коротко о React.js Автор: Александр Вишняков MadDevs
  • 2. О чем поговорим ● React - почему он нужен? ● Flux Utils ● Redux ● Частые ошибки разработчиков
  • 3. React - зачем он нужен? ● Гибкая архитектура ● Разделение ответственностей ● Легкое тестирование ● Переиспользование кода
  • 4. Flux Utils ● Удобное создание Store с использованием ReduceStore<T> ● Контейнеры Container.create() ○ Взаимодействует со всеми Store ○ Освобождает компонент от связности со Store, оставляя только использование action’ов внутри компонента
  • 6. Redux Store ● Все состояния хранятся в едином сторе. Всего один стор на все приложение. ● store.getState() - так получаем содержимое состояния Store ● Состояние нельзя изменять на прямую, минуя экшены. ● У Store как правило, нет публичных методов для изменения состояния. ● Это чистая функция, которая обрабатывает экшены
  • 7. Redux action ● Это обычно просто хеш объект, который отправляется через dispatch({ type: ‘ACTION_TYPE_NAME’, payload: { …. // Данные экшена }, meta: { …. // Служебные данные экшна } })
  • 8. Чистая функция ● Они зависят только от своих параметров. И возвращают только свой результат. ● Не используют никакие глобальные переменные и не изменяют состояние вне тела функции. ○ Math.sin(x) ○ parseInt(x, y) ○ $.ajax() - уже не чистая функция
  • 9. Redux Reducer function reducer(state, action) { switch(action.type){ case ‘SOME_ACTION_TYPE’: return { alias: { ...state.alias, ...action.payload } } default: return state } }
  • 10. Redux сайд-эффекты ● Сайд-эффект - это когда приходится изменять состояние глобально, к примеру после обращения к API ● В классической схеме Flux паттерна, нет места таким манипуляциям. ● Для обработки сайд-эффектов в Redux присутствует понятие прослойки или Middleware ● Middleware - может быть много, по аналогии с веб фреймворками (схема не нова)
  • 12. Redux middleware const logMiddleware = store => next => action => { console.log(action); next(action); } const store = createStore(store)(reducer, applyMiddleware(logMiddleware))
  • 13. Redux-thunk ● Предоставляет возможность диспатчить функции вместо традиционных объектов, как это принято в Redux. ● В переданной функции мы можем сделать вызов api, проделать какие нибудь вычисления и вызвать dispatch в нужный для нас момент. store.dispatch((dispatch) => { fetch(‘/api/some/data’).then( data => dispatch(successAction(data)), err => dispatch(failAction(err)) ) })
  • 14. Redux-thunk Import thunk from ‘redux-thunk’; const store = createStore(reducer, applyMiddleware(thunk))
  • 15. Redux thunk (пример) const login = (user, password) => dispatch => { const formData = new FormData(); formData.append(“user”, user) formData.append(“password”, password) fetch(‘/login’, { method: ‘POST’, data: formData }).then( data => dispatch(loginSuccess(data)), err => dispatch(loginFail(err))) } store.dispatch(login(‘user1’, ‘password1’))
  • 16. Redux thunk (несколько экшенов за раз) const someAction = () => (dispatch, state) => { dispatch(someAction1(state.alias.field)) dispatch(someAction2()) } store.dispatch(someAction())
  • 17. Redux-saga Сага - собирает всю логику обработки внутрь себя в отличии от thunk, где приходится разбивать на мелкие функции и постоянно их диспатчить. В Saga - все асинхронное выполняется линейно благодаря function* в купе с yeild
  • 18. Redux-saga example function* login(user, password) { const formData = new FormData(); formData.append(“user”, user) formData.append(“password”, password) try { const data = yield call(fetch, ‘/login’, { method: ‘POST’, data: formData }) yield put(dispatch(loginSuccess(data))) } catch(e) { yield put(dispatch(loginFail(e))) } }
  • 19. Redux-saga (типы подписки при помощи takeEvery) function* processAction(api, { payload, meta }) { … } function* subscribeForAction(api) { yield* takeEvery(‘SOME_ACTION_1’, processAction, api) }
  • 20. Redux saga (подписка при помощи take и while) function* processAction(api, { data }, { resource, thunk }) { try { const detail = yield call([api, api.post], `/${resource}`, data) yield put(actions.someSuccessAction(resource, detail, data, thunk)) } catch (e) { yield put(actions.someFailAction(resource, e, data, thunk)) } } function* action1(api) { while(true) { const { payload, meta } = yield take(‘SOME_ACTION_1’, ) yield call(processAction(api, payload, meta)) } }
  • 21. Ошибки разработчиков ● Обертка в ( ) => { … } обработчиков события <Component onClick={ (e) => someHandler(e) } />
  • 22. Ошибки разработчиков ● Использование неправильных значений для свойства key={} компонента { list.each((item, index) => { <Component key={Math.random()} data={item}/> // или <Component key={index} data={item}/> })
  • 23. Ошибки разработчиков ● Рендер коллекции компонентов и хардкод передаваемых данных в событии компонента. ○ Это неверное распределение обязанностей, возложенное на родительский компонент { list.each((item, index) => { <Component key={item.id} data={item} onClick={(e) => onItemSelect(item)}/> }) }