Skip to content

Instantly share code, notes, and snippets.

@cef62
Created July 6, 2016 07:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cef62/ce0641a450a68f775318a3f26f1ddeb7 to your computer and use it in GitHub Desktop.
Save cef62/ce0641a450a68f775318a3f26f1ddeb7 to your computer and use it in GitHub Desktop.
Redux without Redux in React
// User.js
const UPDATE_USER = 'UPDATE_USER'
const defaultUser = {
displayName: null
}
function userReducer(state = defaultUser, action) {
switch (action.type) {
case UPDATE_USER:
return Object.assign({}, state, action.user);
default:
return state
}
}
const updateUser = (user) => ({ type: UPDATE_USER, user })
// Reducer.js
const reducers = {
user: userReducer
}
const checkReducer = (nextState) => {
if (typeof nextState === 'undefined') {
throw new Error(
`A state reducer cannot return an undefined value, `
+ `key: ${key}, action: ${action.type}`
)
}
}
const DEFAULT_ACTION = { type: '__init__' }
function Reducer(state = {}, action = DEFAULT_ACTION) {
let hasChanged = false
const nextState = Object.keys(reducers).reduce((final, key) => {
const reducer = reducers[key]
const previousStateForKey = state[key]
const nextStateForKey = reducer(previousStateForKey, action)
checkReducer(nextStateForKey)
final[key] = nextStateForKey
hasChanged = hasChanged || nextStateForKey !== previousStateForKey
return final
}, {})
return hasChanged ? nextState : state
}
// Store.js
class Store extends React.Component {
constructor(props) {
super(props);
this.state = Reducer(undefined, {});
this.registerActions();
}
registerActions() {
this.actions = {
updateUserAction: (...args) => this.dispatch(updateUser(...args)),
}
}
dispatch(action) {
this.setState((state) => Reducer(state, action));
}
render() {
const props = Object.assign({}, this.actions, this.state);
return React.createElement(App, props);
}
}
// App.js
class App extends React.Component {
constructor(props) {
super(props);
this.state = { name }
this.login = this.login.bind(this)
this.nameChanged = this.nameChanged.bind(this)
}
nameChanged(evt) {
this.setState({ name: evt.target.value })
}
login() {
this.props.updateUserAction({ displayName: this.state.name })
}
render() {
return(
<div>
<h1>Hello, {this.props.user.displayName}</h1>
<input
value={this.state.name}
onChange={this.nameChanged}/>
<button onClick={this.login}>Login</button>
</div>
)
}
}
App.propTypes = {
user: React.PropTypes.shape({
displayName: React.PropTypes.string
})
}
ReactDOM.render(
<Store><App /></Store>,
document.getElementById('root')
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment