Plain Redux app w/ "connect()"
/*
Attempt to do the following,
- fix the "divide by zero" display bug
- add a feature allowing the user to select multiplication or division
*/
const Redux = require('redux');
// Action creators
const actions = {
chooseDividend: (value) => ({ type: 'choose-dividend', payload: value }),
chooseDivisor: (value) => ({ type: 'choose-divisor', payload: value })
};
// Implement the "brains" of this app as a Redux store
const initialState = {
dividend: null,
divisor: null
};
const store = Redux.createStore((state = initialState, action) => {
switch(action.type) {
case 'choose-dividend': {
return {
...state,
dividend: action.payload
};
}
case 'choose-divisor': {
return {
...state,
divisor: action.payload
};
}
default: {
return state;
}
}
});
// Define the UI
const UI = {
props: {},
render() {
const first = this.props.firstNumber;
const second = this.props.secondNumber;
const hasFirst = (first !== null);
const hasSecond = (second !== null);
const firstDisplay = hasFirst ? first : '???';
const secondDisplay = hasSecond ? second : '???';
const resultDisplay = (hasFirst && hasSecond) ? this.props.result : '???';
console.log(`${firstDisplay} / ${secondDisplay} = ${resultDisplay}`);
}
};
// Connect state and dispatches to the UI
const ConnectedUI = connect(
(state) => {
return {
firstNumber: state.dividend,
secondNumber: state.divisor,
result: state.dividend / state.divisor
};
},
{
changeFirstNumber: actions.chooseDividend,
changeSecondNumber: actions.chooseDivisor
}
)
(UI);
// Re-display the UI when the state changes by displaying it in the console
store.subscribe(() => ConnectedUI.render());
// Interact with the UI
ConnectedUI.props.changeFirstNumber(2);
ConnectedUI.props.changeSecondNumber(2);
ConnectedUI.props.changeFirstNumber(6);
ConnectedUI.props.changeSecondNumber(null);
ConnectedUI.props.changeSecondNumber(4);
ConnectedUI.props.changeSecondNumber(0); // Ahh!! A bug!
// Implement similar API to react-redux's connect()
function connect (mapState, mapDispatch) {
// UI props
const props = {};
// Connect mapped state
store.subscribe(() => {
Object.assign(props, mapState(store.getState()));
});
// Connect dispatches
Object.keys(mapDispatch).forEach((prop) => {
props[prop] = (...args) => store.dispatch(mapDispatch[prop](...args));
});
// Return adjusted UI, with this.props
return (UI) => Object.assign({}, UI, { props });
};
no comments