SlideShare ist ein Scribd-Unternehmen logo
1 von 164
Downloaden Sie, um offline zu lesen
ES6 Patterns in the Wild
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}
const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
export default thunk;
Code to Run
(wild code)
Code to Run
(wild code)
Code we write Code we import
Code to Run
(wild code)
Code we write Code we import
$$
Code to Teach
Code to Teach
Tutorials
Code to Teach
Tutorials
Documentation
Style Guides
Stack Overflow
Books
Conferences
Code to Teach
Tutorials
Documentation
Style Guides
Stack Overflow
Books
Conferences
Good Stuff
Syntax
SELECT ID, NAME, AGE, AMOUNT
FROM CUSTOMERS, ORDERS
WHERE CUSTOMERS.ID = ORDERS.CUSTOMER_ID;
Unreadable
Pattern
Complexity
What we
expect
What we
get
Code to Teach
Code to Run
Code to Teach
Code to Run
Simple
Complex
Complex
Simple
Joe Morgan
Lawrence, KS
I Write Code
Joe Morgan
Joe Morgan
Read
Joe Morgan
Read
Read
Critically
Reading Code
Redux
{
donuts: [
“chocolate”,
],
filter: null
}
state.donuts.map(donut => {
return (
<h2> {{donut}} </h2>
)
})
<h2> Chocolate </h2>
State Component
{
donuts: [
“chocolate”,
],
filter: null
}
state.donuts.map(donut => {
return (
<h2> {{donut}} </h2>
)
})
<h2> Chocolate </h2>
State Component
dispatch(addDonut(‘maple’))
{
donuts: [
“chocolate”,
“maple”,
],
filter: null
}
state.donuts.map(donut => {
return (
<h2> {{donut}} </h2>
)
})
<h2> Chocolate </h2>
State Component
dispatch(addDonut(‘maple’))
updated state
{
donuts: [
“chocolate”,
“maple”,
],
filter: null
}
state.donuts.map(donut => {
return (
<h2> {{donut}} </h2>
)
})
<h2> Chocolate </h2>
State Component
dispatch(addDonut(‘maple’))
updated state
{
donuts: [
“chocolate”,
“maple”,
],
filter: null
}
state.donuts.map(donut => {
return (
<h2> {{donut}} </h2>
)
})
<h2> Chocolate </h2>
<h2> Maple </h2>
State Component
dispatch(addDonut(‘maple’))
Redux
Functional
Array Methods
High Order Functions
Curry/Partially Applied
Functions
Redux
updated state
{
donuts: [
“chocolate”,
“maple”,
],
filter: null
}
state.donuts.map(donut =>
{
return (
<h2> {{donut}} </h2>
)
}
<h2> Chocolate </h2>
<h2> Maple </h2>
State Component
dispatch(addDonut(‘maple’))
Middleware
Middleware
import compose from './compose'
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
var store = createStore(reducer, preloadedState, enhancer)
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
}
}
}
import compose from './compose'
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
}
}
Arrow Functions
import compose from './compose'
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
}
}
import compose from './compose'
export default function applyMiddleware(...middlewares) {
return function(createStore) {
return function (reducer, preloadedState, enhancer) {
var middlewareAPI = {
getState: store.getState,
dispatch: function (action) {
return dispatch(action);
}
}
chain = middlewares.map(function(middleware) {
return middleware(middlewareAPI)
})
}
}
}
import compose from './compose'
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
}
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
chain = middlewares.map(middleware => middleware(middlewareAPI))
chain = middlewares.map((middleware) => {return middleware(middlewareAPI)})
var that = this;
var namer = {
name: 'bill',
say: function() {
var that = this
console.log(this.name);
setTimeout(function() {
console.log(that.name);
},200);
}
}
var that = this;
const namer = {
name: 'bill',
say: function() {
console.log(this.name);
setTimeout(() => {
console.log(this.name);
},200);
}
}
Favor Arrow Functions
Why Read Wild Code?
i. Reading Code is a Skill
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}
const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
export default thunk;
i. Reading Code is a Skill: Intuition
i. Reading Code is a Skill: Intuition
i. Reading Code is a Skill: Intuition
Redux
Rest/Spread
export default function applyMiddleware(...middlewares) {
// Lots of stuff
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
}
}
export default function applyMiddleware(...middlewares) {
// Lots of stuff
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
}
}
(I actually didn’t realize they had different names)
Redux
Rest/Spread
Rest:
list => array
export default function applyMiddleware(...middlewares) {
// Lots of stuff
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
}
}
export default function applyMiddleware(...middlewares)
examples/real-world/src/store/configureStore.dev.js
applyMiddleware(thunk, api, createLogger())
examples/real-world/src/store/configureStore.prod.js
applyMiddleware(thunk, api)
Redux
Rest/Spread
Spread:
array => list
export default function applyMiddleware(...middlewares) {
dispatch = compose(...chain)(store.dispatch)
examples/real-world/src/store/configureStore.dev.js
compose(thunk, api, createLogger())(store.dispatch)
examples/real-world/src/store/configureStore.prod.js
compose(thunk, api)(store.dispatch)
Redux
Rest/Spread
Convert items to arrays
export default function applyMiddleware(...middlewares) {
// Lots of stuff
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
}
}
export default function applyMiddleware(...middlewares) {
// Lots of stuff
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
}
}
Redux
Rest/Spread
Converting array to a new array
without mutations
describe('combineReducers', () => {
it('returns a composite reducer that maps the state keys
to given reducers', () => {
const reducer = combineReducers({
...
action.type === 'push' ? [ ...state, action.value ] :
state
})
describe('combineReducers', () => {
it('returns a composite reducer that maps the state keys
to given reducers', () => {
const reducer = combineReducers({
...
action.type === 'push' ? [ ...state, action.value ] :
state
})
const family = [
{
name: 'Joe',
age: 34
},
{
name: 'Theo',
age: 1
},
{
name: 'Dyan',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
const family = [
{
name: 'Joe',
age: 34
},
{
name: 'Theo',
age: 1
},
{
name: 'Dyan',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
> family.sort(sortAge);
const family = [
{
name: 'Theo',
age: 1
},
{
name: 'Joe',
age: 34
},
{
name: 'Dyan',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
[
{
name: 'Theo',
age: 1
},
{
name: 'Joe',
age: 34
},
{
name: 'Dyan',
age: 34
},
]
const family = [
{
name: 'Theo',
age: 1
},
{
name: 'Joe',
age: 34
},
{
name: 'Dyan',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
const family = [
{
name: 'Theo',
age: 1
},
{
name: 'Joe',
age: 34
},
{
name: 'Dyan',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
> family.sort(sortName);
const family = [
{
name: 'Dyan',
age: 34
},
{
name: 'Joe',
age: 34
},
{
name: 'Theo',
age: 1
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
[
{
name: 'Dyan',
age: 34
},
{
name: 'Joe',
age: 34
},
{
name: 'Theo',
age: 1
},
]
const family = [
{
name: 'Dyan',
age: 34
},
{
name: 'Joe',
age: 34
},
{
name: 'Theo',
age: 1
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
const family = [
{
name: 'Dyan',
age: 34
},
{
name: 'Joe',
age: 34
},
{
name: 'Theo',
age: 1
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
> family.sort(sortAge);
const family = [
{
name: 'Theo',
age: 1
},
{
name: 'Dyan',
age: 34
},
{
name: 'Joe',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
[
{
name: 'Theo',
age: 1
},
{
name: 'Dyan',
age: 34
},
{
name: 'Joe',
age: 34
},
]
const family = [
{
name: 'Theo',
age: 1
},
{
name: 'Dyan',
age: 34
},
{
name: 'Joe',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
const family = [
{
name: 'Joe',
age: 34
},
{
name: 'Theo',
age: 1
},
{
name: 'Dyan',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
const family = [
{
name: 'Joe',
age: 34
},
{
name: 'Theo',
age: 1
},
{
name: 'Dyan',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
> [...family].sort(sortAge);
const family = [
{
name: 'Joe',
age: 34
},
{
name: 'Theo',
age: 1
},
{
name: 'Dyan',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
[
{
name: 'Theo',
age: 1
},
{
name: 'Joe',
age: 34
},
{
name: 'Dyan',
age: 34
},
]
const family = [
{
name: 'Joe',
age: 34
},
{
name: 'Theo',
age: 1
},
{
name: 'Dyan',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
ii. Your code will reflect your reading
ii. Your code will reflect your reading
data structures
architecture
community standards
ii. Your code will reflect your reading
It’s ok to take ideas
from others
ii. Your code will reflect your reading
import compose from './compose'
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
var store = createStore(reducer, preloadedState, enhancer)
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
}
}
}
import compose from './compose'
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
var store = createStore(reducer, preloadedState, enhancer)
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
}
}
}
Redux
Object Spread
Not part of ES6
//.babelrc
{
"plugins": [
...
"transform-object-rest-spread",
],
...
}
Favor Arrow Functions
Favor Array Methods
(map, reduce, find, filter)
Collecting items to arrays
+
Arrow Functions
=
Happiness
Khan Academy
Khan Academy
Consumer code. Not a library.
Khan Academy
Khan Academy
Object Oriented
Complexity hidden behind interface
Popular in typescript (angular 2) world
export default class Expression extends Node {
constructor(...nodes) {
super();
this.type = 'Expression';
this.children = new List(this, ...nodes);
}
toString() {
return `${this.type}:${this.children.toString()}`;
}
toJSON() {
return {
...super.toJSON(),
children: [...f(this.children).map(child => child.toJSON())],
};
}
clone(uniqueId = false) {
...
export default class Expression extends Node {
constructor(...nodes) {
super();
this.type = 'Expression';
this.children = new List(this, ...nodes);
}
toString() {
return `${this.type}:${this.children.toString()}`;
}
toJSON() {
return {
...super.toJSON(),
children: [...f(this.children).map(child => child.toJSON())],
};
}
clone(uniqueId = false) {
...
export default class Expression extends Node {
constructor(...nodes) {
super();
this.type = 'Expression';
this.children = new List(this, ...nodes);
}
toString() {
return `${this.type}:${this.children.toString()}`;
}
toJSON() {
return {
...super.toJSON(),
children: [...f(this.children).map(child => child.toJSON())],
};
}
clone(uniqueId = false) {
...
iii. Feature Popularity
iii. Feature Popularity: Frequency
The more useful the feature the more frequent it will pop up.
iii. Feature Popularity: Frequency
In Shakespeare:
The top 10 most frequently occuring words make up 21.4%
of all words.


The top 100 most frequently occuring words make up 53.9%
of all words.
export default class Expression extends Node {
constructor(...nodes) {
super();
this.type = 'Expression';
this.children = new List(this, ...nodes);
}
toString() {
return `${this.type}:${this.children.toString()}`;
}
toJSON() {
return {
...super.toJSON(),
children: [...f(this.children).map(child => child.toJSON())],
};
}
clone(uniqueId = false) {
...
export default class Expression extends Node {
constructor(...nodes) {
super();
this.children = new List(this, ...nodes);
}
toString() {
return `${this.type}:${this.children.toString()}`;
}
get last() {
return this.children.last;
}
set last(value) {
this.children.last = value;
}
}
const e = new Expression({id:1}, {id:2}, {id:3})
e = {
children: {
first: {
id: 1,
next: {
id: 2,
next: {
id: 3
}
}
},
last: {
id: 3
}
}
}
const e = new Expression({id:1}, {id:2}, {id:3})
e = {
children: {
first: {
id: 1,
next: {
id: 2,
next: {
id: 3
}
}
},
last: {
id: 3
}
}
}
Linked List
Khan Academy
export default class Expression extends Node {
get last() {
return this.children.last;
}
set last(value) {
this.children.last = value;
}
}
Get/Set treats methods like
properties (popular in
typescript)
const e = new Expression({id:1}, {id:2}, {id:3})
e = {
children: {
first: {
id: 1,
next: {
id: 2,
next: {
id: 3
}
}
},
last: {
id: 3
}
}
}
const e = new Expression({id:1}, {id:2}, {id:3})
e = {
children: {
first: {
id: 1,
next: {
id: 2,
next: {
id: 3
}
}
},
last: {
id: 3
}
}
}
e.last;
// { id: 3 }
const e = new Expression({id:1}, {id:2}, {id:3})
e = {
children: {
first: {
id: 1,
next: {
id: 2,
next: {
id: 3
}
}
},
last: {
id: 3
}
}
}
e.last = { id.4 }
const e = new Expression({id:1}, {id:2}, {id:3})
e = {
children: {
first: {
id: 1,
next: {
id: 2,
next: {
id: 3
}
}
},
last: {
id: 4
}
}
}
e.last = { id.4 }
const e = new Expression({id:1}, {id:2}, {id:3})
e = {
children: {
first: {
id: 1,
next: {
id: 2,
next: {
id: 3
}
}
},
last: {
id: 4
}
}
}
e.last = { id.4 }
export default class Expression extends Node {
get last() {
return this.children.last;
}
set last(value) {
this.children.last = value;
}
}
export default class Expression extends Node {
get last() {
return Object.assign(
{}, { name:'last' }, this.children.last
);
}
set last(value) {
this.children.last = value;
}
}
const e = new Expression({id:1}, {id:2}, {id:3})
e = {
children: {
first: {
id: 1,
next: {
id: 2,
next: {
id: 3
}
}
},
last: {
id: 3
}
}
}
e.last
{
name: ‘last’,
id: 3,

}
export default class Expression extends Node {
constructor(...nodes) {
super();
this.children = new List(this, ...nodes);
}
toString() {
return `${this.type}:${this.children.toString()}`;
}
get first() {
return this.children.first;
}
set first(value) {
this.children.first = value;
}
}
export default class Expression extends Node {
toString() {
return `${this.type}:${this.children.toString()}`;
}
}
export default class Expression extends Node {
toString() {
return this.type + ':' + this.children.toString();
}
}
export default class List extends Node {
...
toString() {
let first = true;
for (let node of this) {
if (!first) {
result += ", ";
} else {
first = false;
}
result += node.id;
}
return result;
}
}
export default class List extends Node {
...
toString() {
let first = true;
for (let node of this) {
// Do Stuff with node.id
}
}
}
export default class List extends Node {
...
toString() {
let first = true;
for (let node of this) {
// Do Stuff with node.id
}
}
}
const e = new Expression({id:1}, {id:2}, {id:3})
e = {
children: {
first: {
id: 1,
next: {
id: 2,
next: {
id: 3
}
}
},
last: {
id: 3
}
}
}
const presentation = [
'ES6 Patterns in the Wild',
'Joe Morgan',
]
for(let metadata of presentation) {
console.log(metadata);
}
const presentation = [
'ES6 Patterns in the Wild',
'Joe Morgan',
]
for(let metadata of presentation) {
console.log(metadata);
}
// ES 6 Patterns in the Wild
// Joe Morgan
const presentation = {
title: 'ES6 Patterns in the Wild',
author: 'Joe Morgan',
}
for(let metadata of presentation) {
console.log(metadata);
}
const presentation = {
title: 'ES6 Patterns in the Wild',
author: 'Joe Morgan',
}
for(let metadata of presentation) {
console.log(metadata);
}
> TypeError: presentation[Symbol.iterator] is not a function
export default class List {
...
*[Symbol.iterator]() {
let node = this.first;
while (node != this.last) {
let current = node;
node = node.next;
yield current;
}
if (this.last) {
yield this.last;
}
}
}
export default class List {
...
*[Symbol.iterator]() {
let node = this.first;
while (node != this.last) {
let current = node;
node = node.next;
yield current;
}
if (this.last) {
yield this.last;
}
}
}
iii. Feature Popularity:
Not all features end up being popular
iii. Feature Popularity:
Not all features end up being popular
export default class List {
...
*[Symbol.iterator]() {
let node = this.first;
while (node != this.last) {
let current = node;
node = node.next;
yield current;
}
if (this.last) {
yield this.last;
}
}
}
const e = new Expression({id:1}, {id:2}, {id:3})
e = {
children: {
first: {
id: 1,
next: {
id: 2,
next: {
id: 3
}
}
},
last: {
id: 3
}
}
}
const e = new Expression({id:1}, {id:2}, {id:3})
e = [{id:1}, {id:2}, {id:3}]
Khan Academy
Create Simple Interfaces
React
React
Performance
canUseCollections = (
...
typeof Map === 'function' &&
isNative(Map) &&
...
);
if (canUseCollections) {
var itemMap = new Map();
var rootIDSet = new Set();
setItem = function(id, item) {
itemMap.set(id, item);
};
getItem = function(id) {
return itemMap.get(id);
};
...
}
else {
var itemByKey = {};
var rootByKey = {};
var getKeyFromID = () => {}
var getIDFromKey = () => {}
setItem = function(id, item) {
var key = getKeyFromID(id);
itemByKey[key] = item;
};
getItem = function(id) {
var key = getKeyFromID(id);
return itemByKey[key];
};
...
}
const presentation = {
title: 'ES6 Patterns in the Wild',
author: 'Joe Morgan',
}
> presentation.title
// 'ES6 Patterns in the Wild'
const presentation = {
title: 'ES6 Patterns in the Wild',
author: 'Joe Morgan',
}
> presentation.title
// 'ES6 Patterns in the Wild'
const presentation = new Map();
presentation.set('title', 'ES6 Patterns in
the Wild');
presentation.set('author', 'Joe Morgan');
> presentation.get('title');
// 'ES6 Patterns in the Wild'
const presentation = new Map()
.set('title', 'ES6 Patterns in the Wild')
.set('author', 'Joe Morgan');
> presentation.get('title');
// 'ES6 Patterns in the Wild'
const presentation = new Map([
['title', 'ES6 Patterns in the Wild'],
['author', 'Joe Morgan']
]);
> presentation.get('title');
// 'ES6 Patterns in the Wild'
canUseCollections = (
...
typeof Map === 'function' &&
isNative(Map) &&
...
);
if (canUseCollections) {
var itemMap = new Map();
var rootIDSet = new Set();
setItem = function(id, item) {
itemMap.set(id, item);
};
getItem = function(id) {
return itemMap.get(id);
};
...
}
else {
var itemByKey = {};
var rootByKey = {};
var getKeyFromID = () => {}
var getIDFromKey = () => {}
setItem = function(id, item) {
var key = getKeyFromID(id);
itemByKey[key] = item;
};
getItem = function(id) {
var key = getKeyFromID(id);
return itemByKey[key];
};
...
}
React
React
React
As ES6 becomes native there
are advantages beyond style
Build a Library of Readable Code
Lurk Around Github
Lurk Around Github
Advanced Search
Glance at your dependencies
Have a few authors you like
iv. Code can be beautiful
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}
const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
export default thunk;
var data = [1,2,3,4];
var updated = [];
for(var i = 0; i < data.length; i++) {
updated.push(i*i);
}
return updated;
const data = [1,2,3,4];
return data.map(n => n*n);
Perfection is finally attained not
when there is no longer anything
to add, but when there is no
longer anything to take away
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}
const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
export default thunk;
Joe Morgan
Joe Morgan
@joesmorgan
Joe Morgan
@joesmorgan
thejoemorgan.com
Joe Morgan
@joesmorgan
thejoemorgan.com
https://github.com/jsmapr1

Weitere ähnliche Inhalte

Was ist angesagt?

스위프트를 여행하는 히치하이커를 위한 스타일 안내
스위프트를 여행하는 히치하이커를 위한 스타일 안내스위프트를 여행하는 히치하이커를 위한 스타일 안내
스위프트를 여행하는 히치하이커를 위한 스타일 안내Jung Kim
 
Error Management: Future vs ZIO
Error Management: Future vs ZIOError Management: Future vs ZIO
Error Management: Future vs ZIOJohn De Goes
 
Essentials and Impactful Features of ES6
Essentials and Impactful Features of ES6Essentials and Impactful Features of ES6
Essentials and Impactful Features of ES6Riza Fahmi
 
The Ring programming language version 1.10 book - Part 70 of 212
The Ring programming language version 1.10 book - Part 70 of 212The Ring programming language version 1.10 book - Part 70 of 212
The Ring programming language version 1.10 book - Part 70 of 212Mahmoud Samir Fayed
 
History of jQuery
History of jQueryHistory of jQuery
History of jQueryjeresig
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patternsSamuel ROZE
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at StripeBuilding Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at StripeStripe
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at StripeBuilding Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at StripeMongoDB
 
CQRS and Event Sourcing in a Symfony application
CQRS and Event Sourcing in a Symfony applicationCQRS and Event Sourcing in a Symfony application
CQRS and Event Sourcing in a Symfony applicationSamuel ROZE
 
Beautiful python - PyLadies
Beautiful python - PyLadiesBeautiful python - PyLadies
Beautiful python - PyLadiesAlicia Pérez
 
The evolution of redux action creators
The evolution of redux action creatorsThe evolution of redux action creators
The evolution of redux action creatorsGeorge Bukhanov
 
Node meetup feb_20_12
Node meetup feb_20_12Node meetup feb_20_12
Node meetup feb_20_12jafar104
 
Symfony CoP: Form component
Symfony CoP: Form componentSymfony CoP: Form component
Symfony CoP: Form componentSamuel ROZE
 
Html5 game programming overview
Html5 game programming overviewHtml5 game programming overview
Html5 game programming overview민태 김
 
Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Konstantin Kudryashov
 
Universal JavaScript
Universal JavaScriptUniversal JavaScript
Universal JavaScript名辰 洪
 

Was ist angesagt? (20)

스위프트를 여행하는 히치하이커를 위한 스타일 안내
스위프트를 여행하는 히치하이커를 위한 스타일 안내스위프트를 여행하는 히치하이커를 위한 스타일 안내
스위프트를 여행하는 히치하이커를 위한 스타일 안내
 
Error Management: Future vs ZIO
Error Management: Future vs ZIOError Management: Future vs ZIO
Error Management: Future vs ZIO
 
Essentials and Impactful Features of ES6
Essentials and Impactful Features of ES6Essentials and Impactful Features of ES6
Essentials and Impactful Features of ES6
 
The Ring programming language version 1.10 book - Part 70 of 212
The Ring programming language version 1.10 book - Part 70 of 212The Ring programming language version 1.10 book - Part 70 of 212
The Ring programming language version 1.10 book - Part 70 of 212
 
History of jQuery
History of jQueryHistory of jQuery
History of jQuery
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patterns
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at StripeBuilding Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at Stripe
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at StripeBuilding Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at Stripe
 
mobl
moblmobl
mobl
 
CQRS and Event Sourcing in a Symfony application
CQRS and Event Sourcing in a Symfony applicationCQRS and Event Sourcing in a Symfony application
CQRS and Event Sourcing in a Symfony application
 
Beautiful python - PyLadies
Beautiful python - PyLadiesBeautiful python - PyLadies
Beautiful python - PyLadies
 
The evolution of redux action creators
The evolution of redux action creatorsThe evolution of redux action creators
The evolution of redux action creators
 
Node meetup feb_20_12
Node meetup feb_20_12Node meetup feb_20_12
Node meetup feb_20_12
 
Hidden rocks in Oracle ADF
Hidden rocks in Oracle ADFHidden rocks in Oracle ADF
Hidden rocks in Oracle ADF
 
Symfony CoP: Form component
Symfony CoP: Form componentSymfony CoP: Form component
Symfony CoP: Form component
 
Html5 game programming overview
Html5 game programming overviewHtml5 game programming overview
Html5 game programming overview
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 
Method::Signatures
Method::SignaturesMethod::Signatures
Method::Signatures
 
Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015
 
Universal JavaScript
Universal JavaScriptUniversal JavaScript
Universal JavaScript
 

Ähnlich wie ES6 patterns in the wild

TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript IntroductionDmitry Sheiko
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with GroovyArturo Herrero
 
EcmaScript unchained
EcmaScript unchainedEcmaScript unchained
EcmaScript unchainedEduard Tomàs
 
Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)
Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)
Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)MongoSF
 
code for quiz in my sql
code for quiz  in my sql code for quiz  in my sql
code for quiz in my sql JOYITAKUNDU1
 
Transaction is a monad
Transaction is a  monadTransaction is a  monad
Transaction is a monadJarek Ratajski
 
Build Lightweight Web Module
Build Lightweight Web ModuleBuild Lightweight Web Module
Build Lightweight Web ModuleMorgan Cheng
 
JAVA...With N.E.T_B.E.A.N.S___________________________________.pdf
JAVA...With N.E.T_B.E.A.N.S___________________________________.pdfJAVA...With N.E.T_B.E.A.N.S___________________________________.pdf
JAVA...With N.E.T_B.E.A.N.S___________________________________.pdfcalderoncasto9163
 
Imugi: Compiler made with Python
Imugi: Compiler made with PythonImugi: Compiler made with Python
Imugi: Compiler made with PythonHan Lee
 
A swift introduction to Swift
A swift introduction to SwiftA swift introduction to Swift
A swift introduction to SwiftGiordano Scalzo
 
Kamil Chmielewski, Jacek Juraszek - "Hadoop. W poszukiwaniu złotego młotka."
Kamil Chmielewski, Jacek Juraszek - "Hadoop. W poszukiwaniu złotego młotka."Kamil Chmielewski, Jacek Juraszek - "Hadoop. W poszukiwaniu złotego młotka."
Kamil Chmielewski, Jacek Juraszek - "Hadoop. W poszukiwaniu złotego młotka."sjabs
 
VISUALIZAR REGISTROS EN UN JTABLE
VISUALIZAR REGISTROS EN UN JTABLEVISUALIZAR REGISTROS EN UN JTABLE
VISUALIZAR REGISTROS EN UN JTABLEDarwin Durand
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Domenic Denicola
 
Damn Fine CoffeeScript
Damn Fine CoffeeScriptDamn Fine CoffeeScript
Damn Fine CoffeeScriptniklal
 

Ähnlich wie ES6 patterns in the wild (20)

TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
 
ES6 Overview
ES6 OverviewES6 Overview
ES6 Overview
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
 
EcmaScript unchained
EcmaScript unchainedEcmaScript unchained
EcmaScript unchained
 
Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)
Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)
Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)
 
SDC - Einführung in Scala
SDC - Einführung in ScalaSDC - Einführung in Scala
SDC - Einführung in Scala
 
code for quiz in my sql
code for quiz  in my sql code for quiz  in my sql
code for quiz in my sql
 
Transaction is a monad
Transaction is a  monadTransaction is a  monad
Transaction is a monad
 
Build Lightweight Web Module
Build Lightweight Web ModuleBuild Lightweight Web Module
Build Lightweight Web Module
 
Introduction to Groovy
Introduction to GroovyIntroduction to Groovy
Introduction to Groovy
 
JAVA...With N.E.T_B.E.A.N.S___________________________________.pdf
JAVA...With N.E.T_B.E.A.N.S___________________________________.pdfJAVA...With N.E.T_B.E.A.N.S___________________________________.pdf
JAVA...With N.E.T_B.E.A.N.S___________________________________.pdf
 
Imugi: Compiler made with Python
Imugi: Compiler made with PythonImugi: Compiler made with Python
Imugi: Compiler made with Python
 
Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015
 
A swift introduction to Swift
A swift introduction to SwiftA swift introduction to Swift
A swift introduction to Swift
 
Kamil Chmielewski, Jacek Juraszek - "Hadoop. W poszukiwaniu złotego młotka."
Kamil Chmielewski, Jacek Juraszek - "Hadoop. W poszukiwaniu złotego młotka."Kamil Chmielewski, Jacek Juraszek - "Hadoop. W poszukiwaniu złotego młotka."
Kamil Chmielewski, Jacek Juraszek - "Hadoop. W poszukiwaniu złotego młotka."
 
VISUALIZAR REGISTROS EN UN JTABLE
VISUALIZAR REGISTROS EN UN JTABLEVISUALIZAR REGISTROS EN UN JTABLE
VISUALIZAR REGISTROS EN UN JTABLE
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
 
Redux vs Alt
Redux vs AltRedux vs Alt
Redux vs Alt
 
React lecture
React lectureReact lecture
React lecture
 
Damn Fine CoffeeScript
Damn Fine CoffeeScriptDamn Fine CoffeeScript
Damn Fine CoffeeScript
 

Mehr von Joe Morgan

Git the easy way
Git the easy wayGit the easy way
Git the easy wayJoe Morgan
 
React Animations
React AnimationsReact Animations
React AnimationsJoe Morgan
 
Reference Interviews: Where the fun never ends
Reference Interviews: Where the fun never endsReference Interviews: Where the fun never ends
Reference Interviews: Where the fun never endsJoe Morgan
 
Statement of Teaching Philosophy
Statement of Teaching PhilosophyStatement of Teaching Philosophy
Statement of Teaching PhilosophyJoe Morgan
 
Library Committee Meeting
Library Committee MeetingLibrary Committee Meeting
Library Committee MeetingJoe Morgan
 

Mehr von Joe Morgan (6)

Git the easy way
Git the easy wayGit the easy way
Git the easy way
 
React Animations
React AnimationsReact Animations
React Animations
 
Reference Interviews: Where the fun never ends
Reference Interviews: Where the fun never endsReference Interviews: Where the fun never ends
Reference Interviews: Where the fun never ends
 
Statement of Teaching Philosophy
Statement of Teaching PhilosophyStatement of Teaching Philosophy
Statement of Teaching Philosophy
 
Option 2
Option 2Option 2
Option 2
 
Library Committee Meeting
Library Committee MeetingLibrary Committee Meeting
Library Committee Meeting
 

Kürzlich hochgeladen

GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdfChristopherTHyatt
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 

Kürzlich hochgeladen (20)

GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 

ES6 patterns in the wild

  • 1. ES6 Patterns in the Wild
  • 2. function createThunkMiddleware(extraArgument) { return ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }; } const thunk = createThunkMiddleware(); thunk.withExtraArgument = createThunkMiddleware; export default thunk;
  • 4. Code to Run (wild code) Code we write Code we import
  • 5. Code to Run (wild code) Code we write Code we import $$
  • 8. Code to Teach Tutorials Documentation Style Guides Stack Overflow Books Conferences
  • 9. Code to Teach Tutorials Documentation Style Guides Stack Overflow Books Conferences Good Stuff
  • 10. Syntax SELECT ID, NAME, AGE, AMOUNT FROM CUSTOMERS, ORDERS WHERE CUSTOMERS.ID = ORDERS.CUSTOMER_ID;
  • 22.
  • 28. Redux
  • 29. { donuts: [ “chocolate”, ], filter: null } state.donuts.map(donut => { return ( <h2> {{donut}} </h2> ) }) <h2> Chocolate </h2> State Component
  • 30. { donuts: [ “chocolate”, ], filter: null } state.donuts.map(donut => { return ( <h2> {{donut}} </h2> ) }) <h2> Chocolate </h2> State Component dispatch(addDonut(‘maple’))
  • 31. { donuts: [ “chocolate”, “maple”, ], filter: null } state.donuts.map(donut => { return ( <h2> {{donut}} </h2> ) }) <h2> Chocolate </h2> State Component dispatch(addDonut(‘maple’))
  • 32. updated state { donuts: [ “chocolate”, “maple”, ], filter: null } state.donuts.map(donut => { return ( <h2> {{donut}} </h2> ) }) <h2> Chocolate </h2> State Component dispatch(addDonut(‘maple’))
  • 33. updated state { donuts: [ “chocolate”, “maple”, ], filter: null } state.donuts.map(donut => { return ( <h2> {{donut}} </h2> ) }) <h2> Chocolate </h2> <h2> Maple </h2> State Component dispatch(addDonut(‘maple’))
  • 34. Redux Functional Array Methods High Order Functions Curry/Partially Applied Functions
  • 35. Redux
  • 36. updated state { donuts: [ “chocolate”, “maple”, ], filter: null } state.donuts.map(donut => { return ( <h2> {{donut}} </h2> ) } <h2> Chocolate </h2> <h2> Maple </h2> State Component dispatch(addDonut(‘maple’)) Middleware Middleware
  • 37. import compose from './compose' export default function applyMiddleware(...middlewares) { return (createStore) => (reducer, preloadedState, enhancer) => { var store = createStore(reducer, preloadedState, enhancer) 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 } } }
  • 38. import compose from './compose' export default function applyMiddleware(...middlewares) { return (createStore) => (reducer, preloadedState, enhancer) => { var middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action) } chain = middlewares.map(middleware => middleware(middlewareAPI)) } } Arrow Functions
  • 39. import compose from './compose' export default function applyMiddleware(...middlewares) { return (createStore) => (reducer, preloadedState, enhancer) => { var middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action) } chain = middlewares.map(middleware => middleware(middlewareAPI)) } }
  • 40. import compose from './compose' export default function applyMiddleware(...middlewares) { return function(createStore) { return function (reducer, preloadedState, enhancer) { var middlewareAPI = { getState: store.getState, dispatch: function (action) { return dispatch(action); } } chain = middlewares.map(function(middleware) { return middleware(middlewareAPI) }) } } }
  • 41. import compose from './compose' export default function applyMiddleware(...middlewares) { return (createStore) => (reducer, preloadedState, enhancer) => { var middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action) } chain = middlewares.map(middleware => middleware(middlewareAPI)) } }
  • 42. chain = middlewares.map(middleware => middleware(middlewareAPI))
  • 43. chain = middlewares.map(middleware => middleware(middlewareAPI)) chain = middlewares.map((middleware) => {return middleware(middlewareAPI)})
  • 44. var that = this;
  • 45. var namer = { name: 'bill', say: function() { var that = this console.log(this.name); setTimeout(function() { console.log(that.name); },200); } }
  • 46. var that = this;
  • 47. const namer = { name: 'bill', say: function() { console.log(this.name); setTimeout(() => { console.log(this.name); },200); } }
  • 49. Why Read Wild Code?
  • 50. i. Reading Code is a Skill
  • 51. function createThunkMiddleware(extraArgument) { return ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }; } const thunk = createThunkMiddleware(); thunk.withExtraArgument = createThunkMiddleware; export default thunk;
  • 52. i. Reading Code is a Skill: Intuition
  • 53. i. Reading Code is a Skill: Intuition
  • 54. i. Reading Code is a Skill: Intuition
  • 55. Redux Rest/Spread export default function applyMiddleware(...middlewares) { // Lots of stuff chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) } }
  • 56. export default function applyMiddleware(...middlewares) { // Lots of stuff chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) } } (I actually didn’t realize they had different names)
  • 58. export default function applyMiddleware(...middlewares) { // Lots of stuff chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) } }
  • 59. export default function applyMiddleware(...middlewares) examples/real-world/src/store/configureStore.dev.js applyMiddleware(thunk, api, createLogger()) examples/real-world/src/store/configureStore.prod.js applyMiddleware(thunk, api)
  • 61. export default function applyMiddleware(...middlewares) { dispatch = compose(...chain)(store.dispatch) examples/real-world/src/store/configureStore.dev.js compose(thunk, api, createLogger())(store.dispatch) examples/real-world/src/store/configureStore.prod.js compose(thunk, api)(store.dispatch)
  • 63. export default function applyMiddleware(...middlewares) { // Lots of stuff chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) } }
  • 64. export default function applyMiddleware(...middlewares) { // Lots of stuff var middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action) } chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) } }
  • 65. Redux Rest/Spread Converting array to a new array without mutations
  • 66. describe('combineReducers', () => { it('returns a composite reducer that maps the state keys to given reducers', () => { const reducer = combineReducers({ ... action.type === 'push' ? [ ...state, action.value ] : state })
  • 67. describe('combineReducers', () => { it('returns a composite reducer that maps the state keys to given reducers', () => { const reducer = combineReducers({ ... action.type === 'push' ? [ ...state, action.value ] : state })
  • 68. const family = [ { name: 'Joe', age: 34 }, { name: 'Theo', age: 1 }, { name: 'Dyan', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 }
  • 69. const family = [ { name: 'Joe', age: 34 }, { name: 'Theo', age: 1 }, { name: 'Dyan', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 } > family.sort(sortAge);
  • 70. const family = [ { name: 'Theo', age: 1 }, { name: 'Joe', age: 34 }, { name: 'Dyan', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 } [ { name: 'Theo', age: 1 }, { name: 'Joe', age: 34 }, { name: 'Dyan', age: 34 }, ]
  • 71. const family = [ { name: 'Theo', age: 1 }, { name: 'Joe', age: 34 }, { name: 'Dyan', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 }
  • 72. const family = [ { name: 'Theo', age: 1 }, { name: 'Joe', age: 34 }, { name: 'Dyan', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 } > family.sort(sortName);
  • 73. const family = [ { name: 'Dyan', age: 34 }, { name: 'Joe', age: 34 }, { name: 'Theo', age: 1 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 } [ { name: 'Dyan', age: 34 }, { name: 'Joe', age: 34 }, { name: 'Theo', age: 1 }, ]
  • 74. const family = [ { name: 'Dyan', age: 34 }, { name: 'Joe', age: 34 }, { name: 'Theo', age: 1 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 }
  • 75. const family = [ { name: 'Dyan', age: 34 }, { name: 'Joe', age: 34 }, { name: 'Theo', age: 1 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 } > family.sort(sortAge);
  • 76. const family = [ { name: 'Theo', age: 1 }, { name: 'Dyan', age: 34 }, { name: 'Joe', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 } [ { name: 'Theo', age: 1 }, { name: 'Dyan', age: 34 }, { name: 'Joe', age: 34 }, ]
  • 77. const family = [ { name: 'Theo', age: 1 }, { name: 'Dyan', age: 34 }, { name: 'Joe', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 }
  • 78. const family = [ { name: 'Joe', age: 34 }, { name: 'Theo', age: 1 }, { name: 'Dyan', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 }
  • 79. const family = [ { name: 'Joe', age: 34 }, { name: 'Theo', age: 1 }, { name: 'Dyan', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 } > [...family].sort(sortAge);
  • 80. const family = [ { name: 'Joe', age: 34 }, { name: 'Theo', age: 1 }, { name: 'Dyan', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 } [ { name: 'Theo', age: 1 }, { name: 'Joe', age: 34 }, { name: 'Dyan', age: 34 }, ]
  • 81. const family = [ { name: 'Joe', age: 34 }, { name: 'Theo', age: 1 }, { name: 'Dyan', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 }
  • 82. ii. Your code will reflect your reading
  • 83. ii. Your code will reflect your reading data structures architecture community standards
  • 84. ii. Your code will reflect your reading It’s ok to take ideas from others
  • 85. ii. Your code will reflect your reading
  • 86. import compose from './compose' export default function applyMiddleware(...middlewares) { return (createStore) => (reducer, preloadedState, enhancer) => { var store = createStore(reducer, preloadedState, enhancer) 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 } } }
  • 87. import compose from './compose' export default function applyMiddleware(...middlewares) { return (createStore) => (reducer, preloadedState, enhancer) => { var store = createStore(reducer, preloadedState, enhancer) 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 } } }
  • 91. Favor Array Methods (map, reduce, find, filter)
  • 92. Collecting items to arrays + Arrow Functions = Happiness
  • 94. Khan Academy Consumer code. Not a library.
  • 96. Khan Academy Object Oriented Complexity hidden behind interface Popular in typescript (angular 2) world
  • 97.
  • 98. export default class Expression extends Node { constructor(...nodes) { super(); this.type = 'Expression'; this.children = new List(this, ...nodes); } toString() { return `${this.type}:${this.children.toString()}`; } toJSON() { return { ...super.toJSON(), children: [...f(this.children).map(child => child.toJSON())], }; } clone(uniqueId = false) { ...
  • 99. export default class Expression extends Node { constructor(...nodes) { super(); this.type = 'Expression'; this.children = new List(this, ...nodes); } toString() { return `${this.type}:${this.children.toString()}`; } toJSON() { return { ...super.toJSON(), children: [...f(this.children).map(child => child.toJSON())], }; } clone(uniqueId = false) { ...
  • 100. export default class Expression extends Node { constructor(...nodes) { super(); this.type = 'Expression'; this.children = new List(this, ...nodes); } toString() { return `${this.type}:${this.children.toString()}`; } toJSON() { return { ...super.toJSON(), children: [...f(this.children).map(child => child.toJSON())], }; } clone(uniqueId = false) { ...
  • 102. iii. Feature Popularity: Frequency The more useful the feature the more frequent it will pop up.
  • 103. iii. Feature Popularity: Frequency In Shakespeare: The top 10 most frequently occuring words make up 21.4% of all words. 
 The top 100 most frequently occuring words make up 53.9% of all words.
  • 104. export default class Expression extends Node { constructor(...nodes) { super(); this.type = 'Expression'; this.children = new List(this, ...nodes); } toString() { return `${this.type}:${this.children.toString()}`; } toJSON() { return { ...super.toJSON(), children: [...f(this.children).map(child => child.toJSON())], }; } clone(uniqueId = false) { ...
  • 105. export default class Expression extends Node { constructor(...nodes) { super(); this.children = new List(this, ...nodes); } toString() { return `${this.type}:${this.children.toString()}`; } get last() { return this.children.last; } set last(value) { this.children.last = value; } }
  • 106. const e = new Expression({id:1}, {id:2}, {id:3}) e = { children: { first: { id: 1, next: { id: 2, next: { id: 3 } } }, last: { id: 3 } } }
  • 107. const e = new Expression({id:1}, {id:2}, {id:3}) e = { children: { first: { id: 1, next: { id: 2, next: { id: 3 } } }, last: { id: 3 } } } Linked List
  • 109. export default class Expression extends Node { get last() { return this.children.last; } set last(value) { this.children.last = value; } }
  • 110. Get/Set treats methods like properties (popular in typescript)
  • 111. const e = new Expression({id:1}, {id:2}, {id:3}) e = { children: { first: { id: 1, next: { id: 2, next: { id: 3 } } }, last: { id: 3 } } }
  • 112. const e = new Expression({id:1}, {id:2}, {id:3}) e = { children: { first: { id: 1, next: { id: 2, next: { id: 3 } } }, last: { id: 3 } } } e.last; // { id: 3 }
  • 113. const e = new Expression({id:1}, {id:2}, {id:3}) e = { children: { first: { id: 1, next: { id: 2, next: { id: 3 } } }, last: { id: 3 } } } e.last = { id.4 }
  • 114. const e = new Expression({id:1}, {id:2}, {id:3}) e = { children: { first: { id: 1, next: { id: 2, next: { id: 3 } } }, last: { id: 4 } } } e.last = { id.4 }
  • 115. const e = new Expression({id:1}, {id:2}, {id:3}) e = { children: { first: { id: 1, next: { id: 2, next: { id: 3 } } }, last: { id: 4 } } } e.last = { id.4 }
  • 116. export default class Expression extends Node { get last() { return this.children.last; } set last(value) { this.children.last = value; } }
  • 117. export default class Expression extends Node { get last() { return Object.assign( {}, { name:'last' }, this.children.last ); } set last(value) { this.children.last = value; } }
  • 118. const e = new Expression({id:1}, {id:2}, {id:3}) e = { children: { first: { id: 1, next: { id: 2, next: { id: 3 } } }, last: { id: 3 } } } e.last { name: ‘last’, id: 3,
 }
  • 119. export default class Expression extends Node { constructor(...nodes) { super(); this.children = new List(this, ...nodes); } toString() { return `${this.type}:${this.children.toString()}`; } get first() { return this.children.first; } set first(value) { this.children.first = value; } }
  • 120. export default class Expression extends Node { toString() { return `${this.type}:${this.children.toString()}`; } }
  • 121. export default class Expression extends Node { toString() { return this.type + ':' + this.children.toString(); } }
  • 122. export default class List extends Node { ... toString() { let first = true; for (let node of this) { if (!first) { result += ", "; } else { first = false; } result += node.id; } return result; } }
  • 123. export default class List extends Node { ... toString() { let first = true; for (let node of this) { // Do Stuff with node.id } } }
  • 124. export default class List extends Node { ... toString() { let first = true; for (let node of this) { // Do Stuff with node.id } } }
  • 125. const e = new Expression({id:1}, {id:2}, {id:3}) e = { children: { first: { id: 1, next: { id: 2, next: { id: 3 } } }, last: { id: 3 } } }
  • 126. const presentation = [ 'ES6 Patterns in the Wild', 'Joe Morgan', ] for(let metadata of presentation) { console.log(metadata); }
  • 127. const presentation = [ 'ES6 Patterns in the Wild', 'Joe Morgan', ] for(let metadata of presentation) { console.log(metadata); } // ES 6 Patterns in the Wild // Joe Morgan
  • 128. const presentation = { title: 'ES6 Patterns in the Wild', author: 'Joe Morgan', } for(let metadata of presentation) { console.log(metadata); }
  • 129. const presentation = { title: 'ES6 Patterns in the Wild', author: 'Joe Morgan', } for(let metadata of presentation) { console.log(metadata); } > TypeError: presentation[Symbol.iterator] is not a function
  • 130. export default class List { ... *[Symbol.iterator]() { let node = this.first; while (node != this.last) { let current = node; node = node.next; yield current; } if (this.last) { yield this.last; } } }
  • 131. export default class List { ... *[Symbol.iterator]() { let node = this.first; while (node != this.last) { let current = node; node = node.next; yield current; } if (this.last) { yield this.last; } } }
  • 132. iii. Feature Popularity: Not all features end up being popular
  • 133. iii. Feature Popularity: Not all features end up being popular
  • 134. export default class List { ... *[Symbol.iterator]() { let node = this.first; while (node != this.last) { let current = node; node = node.next; yield current; } if (this.last) { yield this.last; } } }
  • 135. const e = new Expression({id:1}, {id:2}, {id:3}) e = { children: { first: { id: 1, next: { id: 2, next: { id: 3 } } }, last: { id: 3 } } }
  • 136. const e = new Expression({id:1}, {id:2}, {id:3}) e = [{id:1}, {id:2}, {id:3}]
  • 138. React
  • 140. canUseCollections = ( ... typeof Map === 'function' && isNative(Map) && ... ); if (canUseCollections) { var itemMap = new Map(); var rootIDSet = new Set(); setItem = function(id, item) { itemMap.set(id, item); }; getItem = function(id) { return itemMap.get(id); }; ... } else { var itemByKey = {}; var rootByKey = {}; var getKeyFromID = () => {} var getIDFromKey = () => {} setItem = function(id, item) { var key = getKeyFromID(id); itemByKey[key] = item; }; getItem = function(id) { var key = getKeyFromID(id); return itemByKey[key]; }; ... }
  • 141. const presentation = { title: 'ES6 Patterns in the Wild', author: 'Joe Morgan', } > presentation.title // 'ES6 Patterns in the Wild'
  • 142. const presentation = { title: 'ES6 Patterns in the Wild', author: 'Joe Morgan', } > presentation.title // 'ES6 Patterns in the Wild'
  • 143. const presentation = new Map(); presentation.set('title', 'ES6 Patterns in the Wild'); presentation.set('author', 'Joe Morgan'); > presentation.get('title'); // 'ES6 Patterns in the Wild'
  • 144. const presentation = new Map() .set('title', 'ES6 Patterns in the Wild') .set('author', 'Joe Morgan'); > presentation.get('title'); // 'ES6 Patterns in the Wild'
  • 145. const presentation = new Map([ ['title', 'ES6 Patterns in the Wild'], ['author', 'Joe Morgan'] ]); > presentation.get('title'); // 'ES6 Patterns in the Wild'
  • 146. canUseCollections = ( ... typeof Map === 'function' && isNative(Map) && ... ); if (canUseCollections) { var itemMap = new Map(); var rootIDSet = new Set(); setItem = function(id, item) { itemMap.set(id, item); }; getItem = function(id) { return itemMap.get(id); }; ... } else { var itemByKey = {}; var rootByKey = {}; var getKeyFromID = () => {} var getIDFromKey = () => {} setItem = function(id, item) { var key = getKeyFromID(id); itemByKey[key] = item; }; getItem = function(id) { var key = getKeyFromID(id); return itemByKey[key]; }; ... }
  • 147. React
  • 148. React
  • 149. React As ES6 becomes native there are advantages beyond style
  • 150. Build a Library of Readable Code
  • 153. Glance at your dependencies
  • 154. Have a few authors you like
  • 155. iv. Code can be beautiful
  • 156. function createThunkMiddleware(extraArgument) { return ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }; } const thunk = createThunkMiddleware(); thunk.withExtraArgument = createThunkMiddleware; export default thunk;
  • 157. var data = [1,2,3,4]; var updated = []; for(var i = 0; i < data.length; i++) { updated.push(i*i); } return updated;
  • 158. const data = [1,2,3,4]; return data.map(n => n*n);
  • 159. Perfection is finally attained not when there is no longer anything to add, but when there is no longer anything to take away
  • 160. function createThunkMiddleware(extraArgument) { return ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }; } const thunk = createThunkMiddleware(); thunk.withExtraArgument = createThunkMiddleware; export default thunk;