Created
January 24, 2018 14:34
-
-
Save dralletje/51535e665a8f84e3fe59a401cbd217f1 to your computer and use it in GitHub Desktop.
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
// @flow | |
import React from 'react'; | |
import shallowEqual from 'shallowequal'; | |
/* | |
// Weird example, but I hope you get the point | |
<Compose | |
toggle={fn => | |
<State initialValue={false} children={(value, change) => ({ value, change })} /> | |
} | |
toggle2={fn => | |
<State initialValue={false} children={(value, change) => ({ value, change })} /> | |
} | |
>{({ toggle, toggle2 }) => | |
<div> | |
<div onClick={() => toggle.change(!toggle.value)}>{toggle.value ? 'True' : 'False'}</div> | |
<div onClick={() => toggle2.change(!toggle2.value)}>{toggle2.value ? 'True2' : 'False2'}</div> | |
</div> | |
}</Compose> | |
*/ | |
export class Compose extends React.Component { | |
props: { | |
[key: string]: (children: () => React$Element<*>) => React$Element<*>, | |
children?: () => React$Element<*>, | |
}; | |
render() { | |
const { children, ...chain } = this.props; | |
const entries = Object.entries(chain); | |
const fn = entries.reduce((acc, [key, wrapFn]) => { | |
// $FlowFixMe | |
return props => wrapFn(value => acc({ ...props, [key]: value })); | |
}, props => (children ? children(props) : null)); | |
return fn(); | |
} | |
} | |
// Still not sure what I should call this | |
export class EmptyC extends React.Component { | |
render() { | |
return null; | |
} | |
} | |
export class State extends React.Component { | |
props: { | |
initialValue: any, | |
children?: (value: any, update: (value: any) => void) => React$Element<*>, | |
}; | |
state = { | |
thing: this.props.initialValue, | |
}; | |
render() { | |
if (!this.props.children) return; | |
return this.props.children(this.state.thing, valueOrFn => { | |
if (typeof valueOrFn === 'function') { | |
this.setState(state => { | |
return { thing: valueOrFn(state.thing) }; | |
}); | |
} else { | |
this.setState({ thing: valueOrFn }); | |
} | |
}); | |
} | |
} | |
type TCleanUp = () => mixed; | |
export class Lifecycle extends React.Component { | |
cleanup: ?TCleanUp; | |
props: { | |
componentDidMount?: () => TCleanUp | mixed, | |
}; | |
componentDidMount() { | |
if (this.props.componentDidMount) { | |
let cleanup = this.props.componentDidMount(); | |
if (typeof cleanup === 'function') { | |
this.cleanup = cleanup; | |
} | |
} | |
} | |
componentWillUnmount() { | |
if (this.cleanup) this.cleanup(); | |
} | |
render() { | |
return this.props.children || null; | |
} | |
} | |
type TOnChangeProps = { | |
values: any, | |
onUpdate: (props: any) => mixed, | |
}; | |
export class OnChange<T: any> extends React.Component { | |
props: TOnChangeProps; | |
componentDidMount() { | |
this.props.onUpdate(this.props.values); | |
} | |
componentDidUpdate(prevProps: TOnChangeProps) { | |
if (!shallowEqual(prevProps.values, this.props.values)) { | |
this.props.onUpdate(this.props.values); | |
} | |
} | |
render() { | |
return null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment