Skip to content

Commit

Permalink
Rewrite of useData
Browse files Browse the repository at this point in the history
  • Loading branch information
mcjazzyfunky committed Feb 12, 2019
1 parent 63679df commit 80f535e
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 71 deletions.
19 changes: 8 additions & 11 deletions src/demo-experimental/demos/custom-uses.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
import { createElement, defineComponent } from '../../modules/core/main'
import { init, useData, useEffect, useProps, useState, Component } from '../../modules/experimental/main'
import { init, useData, useEffect, useState, Component } from '../../modules/experimental/main'

const Demo = defineComponent({
displayName: 'Demo',

render: init(c => {
let
[props, prevProps] = useData(c, useProps(c),
(a, b) => { props = a, prevProps = b }),

[data, prevData] = useData(c, {
const
[,, view] = useData(c, {
time: useTime(c, 1000),
mousePos: useMousePos(c)
}, (a, b) => { data = a, prevData = b })
})

return () => (
return view(({ time, mousePos }) => (
<div>
<div>Time: {data.time.toLocaleTimeString()}</div>
<div>Mouse: {data.mousePos ? `${data.mousePos.x},${data.mousePos.y}` : <i>please move mouse...</i>}</div>
<div>Time: {time.toLocaleTimeString()}</div>
<div>Mouse: {mousePos ? `${mousePos.x},${mousePos.y}` : <i>please move mouse...</i>}</div>
</div>
)
))
})
})

Expand Down
91 changes: 31 additions & 60 deletions src/modules/experimental/main/api/useData.ts
Original file line number Diff line number Diff line change
@@ -1,78 +1,49 @@
import Component from './types/Component'
import useState from './useState'
import useEffect from './useEffect'
import { VirtualNode } from '../../../../modules/core/main'
import useForceUpdate from './useForceUpdate'

type Data = Record<string, any>
type Getters<T extends Data> = { [K in keyof T]: () => T[K]}
type View<T extends Data> = (render: (data: T) => VirtualNode) => () => VirtualNode

function useData<T extends { [K in keyof T]: () => ReturnType<T[K]> }>(
c: Component,
source: T,
action: (current: { [K in keyof T]: ReturnType<T[K]> }, previous: { [K in keyof T]: ReturnType<T[K]>}) => void
): [ { [K in keyof T]: ReturnType<T[K]> }, { [K in keyof T]: ReturnType<T[K]> } ]

function useData<T>(c: Component, get: () => T, action: (current: T, previous: T) => void): [T, T | undefined]

function useData(c: Component, source: any, action: (current: any, previous: any) => void) {
let ret: any

if (typeof source === 'function') {
ret = useSingleData(c, source, action)
} else {
ret = useMultiData(c, source, action)
}

return ret
}

export default useData

// --- local --------------------------------------------------------
function useData<T extends Data>(c: Component, getters: Getters<T>): [T, T, View<T>] {
const
curr: T = {} as T,
prev: T = {} as T,
view: View<T> = (render: (data: T) => VirtualNode) => () => render(curr),
[, setDummy] = useState(c, false)

function useSingleData<T>(c: Component, get: () => T, action: (current: T, previous: T) => void): [T, T | undefined] {
let
current: T = get(),
previous: T = undefined
updateDataObject(curr, getters)
clearDataObject(prev, getters)

useEffect(c, () => {
previous = current
current = get()

action(current, previous)
setDummy((it: boolean) => {
Object.assign(prev, curr)
updateDataObject(curr, getters)
return !it
})
})

action(current, undefined)

return [current, undefined]
return [curr, prev, view]
}

function useMultiData<T>(c: Component, source: { [key: string]: () => any}, action: (current: T, previous: T) => void): [T, T | undefined] {
const
keys = Object.keys(source)

function get() {
const ret: any = {}

for (let i = 0; i < keys.length; ++i) {
const key = keys[i]

ret[key] = source[key]()
function updateDataObject(obj: any, getters: any) {
for (let propName in getters) {
if (getters.hasOwnProperty(propName)) {
obj[propName] = getters[propName]()
}

return ret
}
}

let
current: any = get(),
previous: any = undefined

useEffect(c, () => {
previous = current
current = get()

action(current, previous)
})

action(current, undefined)

return [current, undefined]
function clearDataObject(obj: any, getters: any) {
for (let propName in getters) {
if (getters.hasOwnProperty(propName)) {
obj[propName] = undefined
}
}
}

export default useData

0 comments on commit 80f535e

Please sign in to comment.