Created
October 20, 2016 08:22
-
-
Save undoZen/b6695e370fdcaa1612d2501e0accf194 to your computer and use it in GitHub Desktop.
an failed experiment with freezer-js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict' | |
import Freezer from 'freezer-js' | |
import {assign, isArray, each, toPath} from 'lodash' | |
import h from 'react-hyperscript' | |
import {Component, PureComponent} from 'react' | |
var store = new Freezer({}) | |
export default store | |
console.log(store); | |
export function getNameSpaceAndLastRef(data, p) { | |
var ps = toPath(p) | |
var lpk = ps.pop() | |
return [ps.reduce(function(result, pk, idx) { | |
if (!(pk in result)) { | |
return result.set(pk, {})[pk] | |
} else { | |
return result[pk] | |
} | |
}, data), lpk] | |
} | |
export function getState(p, d) { | |
return getFrom(store.get(), p, d) | |
} | |
console.log(getState()); | |
export function getFrom(data, p, d) { | |
if (!p) return data | |
var [ns, lpk] = getNameSpaceAndLastRef(data, p) | |
return lpk in ns || typeof d === 'undefined' | |
? ns[lpk] | |
: ns.set(lpk, d)[lpk] | |
} | |
export function setState(p, v) { | |
return setTo(store.get(), p, v) | |
} | |
export function setTo(data, p, v) { | |
var [ns, lpk] = getNameSpaceAndLastRef(data, p) | |
return ns.set(lpk, v)[lpk] | |
} | |
export function resetState(p, v) { | |
return resetTo(store.get(), p, v) | |
} | |
export function resetTo(data, p, v) { | |
var [ns, lpk] = getNameSpaceAndLastRef(data, p) | |
if (!(lpk in ns)) { | |
return ns.set(lpk, v)[lpk] | |
} | |
return ns[lpk].reset(v) | |
} | |
export var eventHub = store.getEventHub() | |
export class StoreHOC extends Component { | |
} | |
var actions = {} | |
var updates = {} | |
export function setStore ({actions, updates}) { | |
} | |
console.log('store loaded') | |
export function commit(id, getData, commit, update, payload) { | |
var process = (allUpdates[id] || {})[update] | |
var data = getData() | |
var get = (p, d) => getFrom(getData(), p, d) | |
var set = (p, v) => p ? setTo(getData(), p, v) : getData().set(v) | |
var reset = (p, v) => p ? resetTo(getData(), p, v) : getData().reset(v) | |
console.log('commit', data, arguments); | |
if (typeof process !== 'function') { | |
return get() | |
} | |
process({payload, get, set, reset, commit}) | |
return getData() | |
} | |
export function dispatch(id, getData, dispatch, parentDispatch, commit, action, payload) { | |
console.log('dispatch', arguments); | |
var process = (allActions[id] || {})[action] | |
var data = getData() | |
var get = (p, d) => getFrom(getData(), p, d) | |
var set = (p, v) => p ? setTo(getData(), p, v) : getData().set(v) | |
var reset = (p, v) => p ? resetTo(getData(), p, v) : getData().reset(v) | |
const parent = typeof parentDispatch === 'function' | |
? parentDispatch.bind(null, action, payload) | |
: () => Promise.resolve(null) | |
if (typeof process !== 'function') { | |
return parent() | |
} | |
return Promise.resolve(process({payload, get, set, reset, dispatch, commit, parent}).then(() => null)) | |
} | |
const allActions = {} | |
const allUpdates = {} | |
export function StoreComponent(id, {actions, updates}) { | |
allActions[id] = actions || {} | |
allUpdates[id] = updates || {} | |
return { | |
react: reactHOC(id) | |
} | |
} | |
function reactHOC(id) { | |
return function getReactHOC(viewComponent) { | |
return class extends PureComponent { | |
constructor (props) { | |
super(props) | |
console.log(props) | |
if (!props.data) { | |
throw new Error('props.data required!') | |
} | |
this.dataIsNode = props.data && props.data.__ | |
this.store = new Freezer(this.dataIsNode ? {wrapped: props.data} : props.data) | |
this.getData = () => this.dataIsNode ? this.store.get().wrapped : this.store.get() | |
this.state = { | |
data: this.commit('init') | |
} | |
this.dispatch('init') | |
} | |
commit = (update, payload) => commit(id, this.getData, this.commit, update, payload) | |
dispatch = (action, payload) => dispatch(id, this.getData, this.dispatch, this.props.dispatch, this.commit, action, payload) | |
componentWillReceiveProps (nextProps) { | |
const {data} = nextProps | |
const current = this.getData() | |
if (this.state.data !== current) { | |
this.setState({ | |
data: current | |
}) | |
} | |
if (data === current) { | |
return | |
} | |
if (this.dataIsNode) { | |
const root = this.store.get() | |
if (!data.__ || !data.__.parents) { | |
console.log(1, data, root, current); | |
root.set('wrapped', data) | |
this.dispatch('reset', []) | |
return | |
} | |
if (!data.__.parents.length || data.__.parents.indexOf(root) < 0) { | |
console.log(2, data, root, current); | |
root.set('wrapped', data) | |
this.dispatch('reset', []) | |
return | |
} else { | |
// will eventually trigger updata | |
return | |
} | |
} | |
const changed = Object.keys(data).filter( | |
pk => data[pk] !== current[pk] | |
) | |
if (changed.length) { | |
console.log(changed); | |
const newData = changed.reduce( | |
(state, pk) => { | |
if (state[pk] && state[pk].__) { | |
state[pk].reset(data[pk]) | |
} else { | |
state.set(pk, data[pk]) | |
} | |
return this.getData() | |
}, | |
this.getData() | |
) | |
this.dispatch('reset', changed) | |
} | |
} | |
componentDidMount () { | |
console.log('did mount'); | |
this.updateListener = (function updateListener(newData, oldData) { | |
if (newData !== oldData) { | |
this.setState({ | |
data: this.dataIsNode ? newData.wrapped : newData | |
}) | |
} | |
}.bind(this)) | |
this.store.on('update', this.updateListener) | |
} | |
componentWillUnmount () { | |
console.log('will unmount'); | |
this.store.off('update', this.updateListener) | |
const data = this.store.get() | |
this.store = null | |
data.remove(Object.keys(data)) | |
//this.setState({data: null}) | |
} | |
render() { | |
return h(viewComponent, { | |
...this.props, | |
dispatch: this.dispatch, | |
commit: this.commit, | |
data: this.state.data, | |
get: (p) => getFrom(this.getData(), p) | |
}) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment