Redux Sederhana seperti garu

Saya sudah melihat ke dalam repositori perpustakaan redux , tetapi dari suatu tempat saya mendapat ide untuk menyelidiki implementasinya. Saya ingin berbagi penemuan saya yang mengejutkan atau mengecewakan dengan komunitas.

TL; DR: Logika redux inti sesuai dengan 7 baris kode JS.

Tentang redux secara singkat (terjemahan gratis dari header di github):
Redux adalah perpustakaan manajemen negara untuk aplikasi JavaScript.

Ini membantu untuk menulis aplikasi yang berperilaku stabil / dapat diprediksi, bekerja di lingkungan yang berbeda (klien / server / kode asli) dan mudah diuji.
Saya mengkloning repositori redux , membuka folder sumber di editor (mengabaikan dokumen , contoh , dll.) Dan meraih tombol Delete dengan gunting :

  • Menghapus semua komentar dari kode
    Setiap metode perpustakaan didokumentasikan menggunakan JSDoc dengan sangat rinci.
  • Validasi kesalahan yang dihapus dan pencatatan
    Dalam setiap metode, parameter input dikontrol ketat dengan output komentar rinci yang sangat bagus ke konsol
  • BindActionCreators dihapus, berlangganan , replaceReducer dan metode yang dapat diamati .

    ... karena dia bisa. Ya, atau karena saya terlalu malas untuk menulis contoh untuk mereka. Tetapi tanpa kasus sudut, mereka bahkan kurang menarik dari apa yang ada di depan.

Sekarang mari kita lihat apa yang tersisa



Menulis redux dalam 7 baris


Semua fungsi dasar redux cocok dalam file kecil, yang hampir tidak ada orang yang akan membuat repositori github :)

function createStore(reducer, initialState) {
    let state = initialState
    return {
        dispatch: action => { state = reducer(state, action) },
        getState: () => state,
    }
}

. , , .

redux. 18 HeadHunter «redux» — , , 7 . — .

7 TodoApp. . TodoApp redux.

//  
function todosReducer(state, action) {
  switch (action.type) {
    case 'ADD_TODO':
      return [
        ...state,
        {
          id: action.id,
          text: action.text,
          completed: false
        }
      ]
    case 'TOGGLE_TODO':
      return state.map(todo => {
        if (todo.id === action.id) {
          return { ...todo, completed: !todo.completed }
        }
        return todo
      })
    default:
      return state
  }
}

const initialTodos = []

const store = createStore(todosReducer, initialTodos)

// 
store.dispatch({
  type: 'ADD_TODO',
  id: 1,
  text: '  redux '
})

store.getState() 
// [{ id: 1, text: '  redux ', completed: false }]

store.dispatch({
  type: 'TOGGLE_TODO',
  id: 1
})

store.getState() 
// [{ id: 1, text: '  redux ', completed: true }]

, show must go on.
, .

combineReducers


, , reducer , .

:

//     todosReducer   

function counterReducer(state, action) {
  if (action.type === 'ADD') {
    return state + 1
  } else {
    return state
  }
}

const reducer = combineReducers({
  todoState: todoReducer,
  counterState: counterReducer
})

const initialState = {
  todoState: [],
  counterState: 0,
}

const store = createStore(reducer, initialState)

store , .

TodoApp .

ES6 (7/8/∞):

const reducer = combineReducers({ todos, counter })

todoReducer todos counterReducer counter. . , , redux, , (state.todos) , (function todos(){}).

micro-redux, :

function reducer(state, action) {
  return {
    todoState: todoReducer(state, action),
    counterState: counterReducer(state, action),
  }
}

. 2 «-», (state, action), , ?
, Object.entries
combineReducers (, ) :

function combineReducers(reducersMap) {
  return function combinationReducer(state, action) {
    const nextState = {}
    Object.entries(reducersMap).forEach(([key, reducer]) => {
      nextState[key] = reducer(state[key], action)
    })
    return nextState
  }
}

redux 9 .

, , .

applyMiddleware


middleware redux — - , dispatch -. , , ,… — -.

middleware createStore, , :

const createStoreWithMiddleware = applyMiddleware(someMiddleware)(createStore)
const store = createStoreWithMiddleware(reducer, initialState)

applyMiddleware, 10 , : createStore «dispatch». dispatch, ( ) , — , (newState = reducer(state, action)).
applyMiddleware dispatch, ( ) - .

, , middleware redux — redux-thunk

,

store.dispatch({type: 'SOME_ACTION_TYPE', some_useful_data: 1 })

store.dispatch

function someStrangeAction() {
  return async function(dispatch, getState) {
    if(getState().counterState % 2) {
       dispatch({
         type: 'ADD',
       })
    }
    await new Promise(resolve => setTimeout(resolve, 1000))
    dispatch({
      type: 'TOGGLE_TODO',
      id: 1
    })
  }
}

,

dispatch(someStrangeAction())

:

  • store.getState().counterState 2, 1
  • , todo id=1 completed true false .

, redux-thunk, redux — , ,

:

const thunk = store => dispatch => action => {
  if (typeof action === 'function') {
    return action(store.dispatch, store.getState)
  }
  return dispatch(action)
}

,
const thunk = store => dispatch => action
, , , , , (, , )

, createStore

function createStore(reducer, initialState) {
    let state = initialState
    return {
        dispatch: action => { state = reducer(state, action) },
        getState: () => state,
    }
}

(reducer, initialState) { dispatch, getState }.

, applyMiddleware , , .
createStore :

function applyMiddleware(middleware) {
  return function createStoreWithMiddleware(createStore) {
    return (reducer, state) => {
      const store = createStore(reducer, state)

      return {
        dispatch: action => middleware(store)(store.dispatch)(action),
        getState: store.getState,
      }
    }
  }
}


redux . « , ». , 1 — .

P.S.


«micro-redux» store.subscribe 8 . ?

Source: https://habr.com/ru/post/id439104/


All Articles