Skip to content

Instantly share code, notes, and snippets.

Last active May 5, 2024 15:14
Show Gist options
  • Save gaearon/ffd88b0e4f00b22c3159 to your computer and use it in GitHub Desktop.
Save gaearon/ffd88b0e4f00b22c3159 to your computer and use it in GitHub Desktop.
Redux without the sanity checks in a single file. Don't use this, use normal Redux. :-)
function mapValues(obj, fn) {
return Object.keys(obj).reduce((result, key) => {
result[key] = fn(obj[key], key);
return result;
}, {});
function pick(obj, fn) {
return Object.keys(obj).reduce((result, key) => {
if (fn(obj[key])) {
result[key] = obj[key];
return result;
}, {});
function bindActionCreator(actionCreator, dispatch) {
return (...args) => dispatch(actionCreator(...args));
export function bindActionCreators(actionCreators, dispatch) {
return typeof actionCreators === 'function' ?
bindActionCreator(actionCreators, dispatch) :
mapValues(actionCreators, actionCreator =>
bindActionCreator(actionCreator, dispatch)
export function compose(...funcs) {
return arg => funcs.reduceRight((composed, f) => f(composed), arg);
export function applyMiddleware(...middlewares) {
return (next) => (reducer, initialState) => {
var store = next(reducer, initialState);
var dispatch = store.dispatch;
var chain = [];
chain = => middleware({
getState: store.getState,
dispatch: (action) => dispatch(action)
dispatch = compose(...chain)(store.dispatch);
return {, dispatch };
export function combineReducers(reducers) {
var finalReducers = pick(reducers, (val) => typeof val === 'function');
return (state = {}, action) => mapValues(finalReducers,
(reducer, key) => reducer(state[key], action)
export function createStore(reducer, initialState) {
var currentReducer = reducer;
var currentState = initialState;
var listeners = [];
var isDispatching = false;
function getState() {
return currentState;
function subscribe(listener) {
return function unsubscribe() {
var index = listeners.indexOf(listener);
listeners.splice(index, 1);
function dispatch(action) {
if (isDispatching) {
throw new Error('Reducers may not dispatch actions.');
try {
isDispatching = true;
currentState = currentReducer(currentState, action);
} finally {
isDispatching = false;
listeners.slice().forEach(listener => listener());
return action;
function replaceReducer(nextReducer) {
currentReducer = nextReducer;
dispatch({ type: '@@redux/INIT' });
dispatch({ type: '@@redux/INIT' });
return { dispatch, subscribe, getState, replaceReducer };
Copy link

ptim commented Jun 11, 2017

@sabha you probably found it already, but for those who com after, here is connect explained:

Copy link

Amazingly beautiful code 👍

Copy link

I'm heavily breathing right now. This is just pure awesomeness!

Copy link

It's 2018. Is it too late for me to say 'cool'?

Copy link


Copy link

sag1v commented Mar 28, 2019

4 years later...
I'm curious why you use .slice on this line
listeners.slice().forEach(listener => listener());

Why do we need a new array here?

Copy link

raynerpupo commented Apr 10, 2019

@sag1v while that forEach is a blocking operation it doesn't guarantee that a listener() call wouldn't remove a original listener from the listeners array so by copying the list you won't get weird results. 2nd caveat from here:

Copy link

@sag1v found the possible reason, please read the 2nd caveat here

Copy link

sag1v commented Jun 19, 2020

@raynerpupo For some reason i missed your comments, thanks :)

For other readers, this code snippet can demonstrate what happens if you don't use .slice to create a "snapshot" of the array.
Basically if a listener removes itself from the array, other listeners might not run (due to mutation).

let arr = [func1, func2];
function func1(){
  arr.splice(0, 1) // func1 removes itself from the array
function func2(){
//.slice() // if we don't slice here, func2 wont run
.forEach(fn => fn())

// logs: 1

Copy link

2020, starting to learn redux, and got one confusion for this code snippet:

In the createStore function, there should be a third option argument enhancer right? I checked the redux source code and the createStore function might look this:

function createStore(reducer, preloadedState, enhancer) {
  if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
    enhancer = preloadedState
    preloadedState = undefined

  if (typeof enhancer !== 'undefined') {
    if (typeof enhancer !== 'function') {
      throw new Error('Expected the enhancer to be a function.')

    return enhancer(createStore)(reducer, preloadedState)

  // ... dispatch, subscribe, getState, replaceReducer, 

In this case we can then pass the applyMiddleware to the createStore function:

const store = createStore(

Not sure if my thoughts are reasonable, could someone correct me please?

Copy link

taaemoh commented Oct 7, 2020

I did the same for my Redux Course to explain how really Redux works and what is the concept. I notice that in a lot of courses about Redux, teachers miss the importance of selectors...

Could u please share some link to your course? is it available somewhere?

Copy link

ackvf commented Jan 23, 2024


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment