Ich habe das
Redux- Bibliotheks-
Repository bereits besucht, aber von irgendwoher kam mir die Idee, mich mit seiner Implementierung zu befassen. Ich möchte meine schockierende oder sogar enttäuschende Entdeckung mit der Community teilen.
TL; DR: Die Kern-Redux-Logik passt in 7 Zeilen JS-Code.
Über Redux auf den Punkt gebracht (freie Übersetzung des Headers auf dem Github):
Redux ist eine Statusverwaltungsbibliothek für JavaScript-Anwendungen.
Es ist hilfreich, Anwendungen zu schreiben, die sich stabil / vorhersehbar verhalten, in verschiedenen Umgebungen (Client / Server / nativer Code) arbeiten und einfach getestet werden können.
Ich
klonte das Redux-Repository , öffnete den Quellordner im Editor (ignorierte
Dokumente ,
Beispiele usw.) und
griff mit der
Schere nach der Entf-Taste:
- Alle Kommentare aus dem Code entfernt
Jede Bibliotheksmethode wird mit JSDoc detailliert dokumentiert.
- Fehlerüberprüfung und Protokollierung entfernt
Bei jeder Methode werden die Eingabeparameter streng kontrolliert, wobei sehr schöne detaillierte Kommentare an die Konsole ausgegeben werden
- BindActionCreators , subscribe , replaceReducer und beobachtbare Methoden wurden entfernt .
... weil er konnte. Nun, oder weil ich zu faul war, um Beispiele für sie zu schreiben. Aber ohne Eckfälle sind sie noch weniger interessant als das, was vor uns liegt.
Schauen wir uns nun an, was noch übrig ist
Redux in 7 Zeilen schreiben
Alle grundlegenden Funktionen von Redux passen in eine winzige Datei, für die kaum jemand ein Github-Repository erstellen wird :)
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()
store.dispatch({
type: 'TOGGLE_TODO',
id: 1
})
store.getState()
,
show must go on.
, .
combineReducers
, , reducer , .
:
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
, , , , , (, , )
,
createStorefunction 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 . ?