Skip to content

Instantly share code, notes, and snippets.

@jameskerr
Last active November 23, 2020 19:16
Show Gist options
  • Save jameskerr/6f57ae966b856a6fed2c9c43052b18ae to your computer and use it in GitHub Desktop.
Save jameskerr/6f57ae966b856a6fed2c9c43052b18ae to your computer and use it in GitHub Desktop.
Redux Model
/* This could be a way to reduce (haha) the redux boilerplate. */
import {createStore} from "redux"
function createReduxModel(prefix, config) {
const actionType = (name) => `${prefix}_${name.toUpperCase()}_SET`
class Model {
constructor(store) {
for (const [name] of Object.entries(config)) {
Object.defineProperty(this, name, {
set(value) {
store.dispatch({type: actionType(name), value})
},
get() {
return store.getState()[name]
}
})
}
}
}
const reducers = []
for (const [name] of Object.entries(config)) {
reducers.push((slice, action) => {
if (action.type === actionType(name)) {
return {...slice, [name]: action.value}
} else {
return slice
}
})
}
Model.reducer = (state = config, action) => {
return reducers.reduce((slice, func) => func(slice, action), state)
}
return Model
}
const User = createReduxModel("USER", {
name: "",
age: "",
title: "",
company: ""
})
const store = createStore(User.reducer)
test("Redux Model Example", () => {
const user = new User(store)
user.name = "James" // dispatching behind the scenes
user.age = "30"
user.title = "Software engineer"
user.company = "Brim Security"
expect(user.name).toBe("James") // selecting from the state behind the scenes
expect(user.age).toBe("30")
expect(user.title).toBe("Software engineer")
expect(user.company).toBe("Brim Security")
expect(store.getState()).toEqual({
name: 'James',
age: '30',
title: 'Software engineer',
company: 'Brim Security'
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment