View
Action
Store
const increment = () => ({ type: "INCREMENT" });
function count(state = 0, action) {
switch (action.type) {
case "INCREMENT":
return state + 1;
default:
return state;
}
}
const store = Redux.createStore(count);
const { Provider, connect } = ReactRedux;
const App = connect(
state => ({
count: state
}),
dispatch => ({
increment: () => dispatch(increment())
})
)(
class extends React.Component {
onClick = () => {
this.props.increment();
};
render() {
return (
<div>
<p>Count: {this.props.count}</p>
<button onClick={this.onClick}>+</button>
</div>
);
}
}
);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("app")
);
export default function createStore(reducer, preloadedState, enhancer) {
...
enhancer(createStore)(reducer, preloadedState);
...
function dispatch(action) {
...
try {
isDispatching = true
currentState = currentReducer(currentState, action)
} finally {
isDispatching = false
}
...
return action
}
}
import {
createStore,
applyMiddleware,
} from 'redux';
import customMiddleware1 from './customMiddleware1.js';
import customMiddleware2 from './customMiddleware2.js';
const store = createStore(reducer, defaultState, applyMiddleware(
customMiddleware1,
customMiddleware2,
));
...
export default function App({
store,
history,
}: any) {
return (
<Provider store={store}>
<ConnectedRouter history={history}>
<MainBoard />
</ConnectedRouter>
</Provider>
);
}
export default function applyMiddleware(...middlewares) {
return (next) =>
(reducer, initialState) => {
var store = next(reducer, initialState);
var dispatch = store.dispatch;
var chain = [];
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
};
chain = middlewares.map(middleware =>
middleware(middlewareAPI));
dispatch = compose(...chain, store.dispatch);
return {
...store,
dispatch
};
};
}
given:
f(x) = x^2 + 3x + 1
g(x) = 2x
then:
(f ∘ g)(x) = f(g(x)) = f(2x) = 4x^2 + 6x + 1
var greet = function(x) { return `Hello, ${ x }` };
var emote = function(x) { return `${x} :)` };
var compose = function(f, g) {
return function(x) {
return f(g(x));
}
}
var happyGreeting = compose(greet, emote);
// happyGreeting(“Stanney”) -> Hello, Stanney :)
var curriedAdd = function(a) {
return function(b) {
return a + b;
};
};
var addTen = curriedAdd(10);
addTen(10); //20
By currying and composing your functions you can create powerful new functions that create a pipeline for data processing.
export default function applyMiddleware(...middlewares) {
return (next) =>
(reducer, initialState) => {
var store = next(reducer, initialState);
var dispatch = store.dispatch;
var chain = [];
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
};
chain = middlewares.map(middleware =>
middleware(middlewareAPI));
dispatch = compose(...chain, store.dispatch);
return {
...store,
dispatch
};
};
}
export default function applyMiddleware(...middlewares) {
return (next) =>
(reducer, initialState) => {
var store = next(reducer, initialState);
var dispatch = store.dispatch;
var chain = [];
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
};
chain = middlewares.map(middleware =>
middleware(middlewareAPI));
dispatch = compose(...chain, store.dispatch); <= !!!!!!
return {
...store,
dispatch
};
};
}
dispatch = compose(...chain, store.dispatch);
export default function compose(...funcs) {
return funcs.reduceRight((composed, f) => f(composed));
}
=> middlewareI(middlewareJ(middlewareK(store.dispatch)))(action)
store.dispatch(stanneyTodo('Make Report'))
==
const action = stanneyTodo('Make Report')
console.log('dispatching', action)
store.dispatch(action)
console.log('next state', store.getState())
store.dispatch(stanneyTodo('Make Report'))
==
function dispatchAndLog(store, action) {
console.log('dispatching', action)
store.dispatch(action)
console.log('next state', store.getState())
}
dispatchAndLog(store, stanneyTodo('Make Report'))
store.dispatch(stanneyTodo('Make Report'))
==
const next = store.dispatch
store.dispatch = function dispatchAndLog(action) {
console.log('dispatching', action)
let result = next(action)
console.log('next state', store.getState())
return result
}
function showLogging(store) {
const next = store.dispatch
store.dispatch = function dispatchAndLog(action) {
console.log('dispatching', action)
let result = next(action)
console.log('next state', store.getState())
return result
}
}
function showCrashReporting(store) {
const next = store.dispatch
store.dispatch = function dispatchAndReportErrors(action) {
try {
return next(action)
} catch (err) {
console.error('Error', err)
Raven.captureException(err, {
extra: {
action,
state: store.getState()
}
})
throw err
}
}
}
showLogging(store)
showCrashReporting(store)
function showLogging(store) {
const next = store.dispatch
store.dispatch = function dispatchAndLog(action) {
console.log('dispatching', action)
let result = next(action)
console.log('next state', store.getState())
return result
}
}
function showCrashReporting(store) {
const next = store.dispatch
store.dispatch = function dispatchAndReportErrors(action) {
try {
return next(action)
} catch (err) {
console.error('Error', err)
Raven.captureException(err, {
extra: {
action,
state: store.getState()
}
})
throw err
}
}
}
function logger(store) {
const next = store.dispatch
// Before:
// store.dispatch = function dispatchAndLog(action) {
return function dispatchAndLog(action) {
console.log('dispatching', action)
let result = next(action)
console.log('next state', store.getState())
return result
}
}
function applyMiddleware(store, middlewares) {
middlewares = middlewares.slice()
middlewares.reverse()
// 在每一個 middleware 中變換 dispatch
middlewares.forEach(middleware => (store.dispatch = middleware(store)))
}
applyMiddleware(store, [logger, crashReporter])
function logger(store) {
return function wrapDispatchToAddLogging(next) {
return function dispatchAndLog(action) {
console.log('dispatching', action)
let result = next(action)
console.log('next state', store.getState())
return result
}
}
}
function applyMiddleware(store, middlewares) {
middlewares = middlewares.slice()
middlewares.reverse()
// 在每一個 middleware 中變換 dispatch
middlewares.forEach(middleware => (store.dispatch = middleware(store)))
}
applyMiddleware(store, [logger, crashReporter])
const logger = store => next => action => {
console.log('dispatching', action)
let result = next(action)
console.log('next state', store.getState())
return result
}
const crashReporter = store => next => action => {
try {
return next(action)
} catch (err) {
console.error('Caught an exception!', err)
Raven.captureException(err, {
extra: {
action,
state: store.getState()
}
})
throw err
}
}