Skip to content

Instantly share code, notes, and snippets.

@davidbalbert
Last active December 14, 2016 21:37
Show Gist options
  • Select an option

  • Save davidbalbert/65cc0486f3dffc7d6ed8ee489d8a647f to your computer and use it in GitHub Desktop.

Select an option

Save davidbalbert/65cc0486f3dffc7d6ed8ee489d8a647f to your computer and use it in GitHub Desktop.
mini redux
// Redux
function createStore(reducer) {
let state;
let listeners = [];
const store = {
dispatch(action) {
state = reducer(state, action);
for (let l of listeners) {
l();
}
},
getReducer() {
return reducer;
},
getState() {
return state;
},
replaceReducer(newReducer) {
reducer = newReducer;
},
subscribe(listener) {
listeners.push(listener);
}
};
store.dispatch({type: "@@redux/INIT"});
return store;
}
// ReactRedux
const { Component, PropTypes } = React;
class Provider extends Component {
static propTypes = {
store: PropTypes.object.isRequired
};
static childContextTypes = {
store: PropTypes.object
};
componentDidMount() {
this.props.store.subscribe(this.storeChanged);
}
getChildContext() {
return {store: this.props.store};
}
storeChanged = () => {
this.forceUpdate();
}
render() {
return this.props.children;
}
}
function connect(mapStateToProps, mapDispatchToProps) {
return WrappedComponent => {
class Connected extends Component {
static contextTypes = {
store: PropTypes.object
};
static WrappedComponent = WrappedComponent;
static name = `Connect(${WrappedComponent.name})`;
render() {
const { store } = this.context;
let props = {};
let dispatchProps = {};
if (mapStateToProps) {
props = mapStateToProps(store.getState());
}
if (mapDispatchToProps) {
dispatchProps = mapDispatchToProps(store.dispatch);
}
return <WrappedComponent { ...props } { ...dispatchProps } dispatch={ store.dispatch } />;
}
}
return Connected;
};
}
// The app
const Actions = {
inc() {
return {
type: "INC"
};
},
dec() {
return {
type: "DEC"
};
}
};
@connect(state => state)
class Counter extends Component {
static propTypes = {
count: PropTypes.number.isRequired,
};
static contextTypes = {
store: PropTypes.object,
};
inc = () => {
this.context.store.dispatch(Actions.inc());
}
dec = () => {
this.context.store.dispatch(Actions.dec());
}
render() {
return (
<div>
{this.props.count}
<button onClick={ this.inc }>+1</button>
<button onClick={ this.dec }>-1</button>
</div>
);
}
}
const initialState = {
count: 0,
}
function reducer(state = initialState, action) {
switch (action.type) {
case "INC":
return { count: state.count + 1 };
case "DEC":
return { count: state.count - 1 };
default:
console.warn(`Unknown action type: ${action.type}`)
return state;
}
}
const store = createStore(reducer);
ReactDOM.render(
<Provider store={ store }><Counter /></Provider>,
document.getElementById('app')
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment