Skip to content

Instantly share code, notes, and snippets.

@cdock1029
Last active September 21, 2018 21:33
Show Gist options
  • Save cdock1029/c6cb282cfb98338f591d636bff1a4bd9 to your computer and use it in GitHub Desktop.
Save cdock1029/c6cb282cfb98338f591d636bff1a4bd9 to your computer and use it in GitHub Desktop.
simple componentFromStream
import React from 'react'
import { Component } from 'react'
import { BehaviorSubject } from 'rxjs'
import { createSubscription } from 'create-subscription'
export const componentFromStream = (
myPipe,
doRender = ({ children, ...rest }) => children(rest)
) => {
const Sub = createSubscription({
getCurrentValue(source) {
return source.getValue()
},
subscribe(source, callback) {
const props$ = source.pipe(myPipe)
const sub = props$.subscribe(props => callback(props))
return () => sub.unsubscribe()
}
})
return class Comp extends Component {
constructor(props) {
super(props)
this.subject = new BehaviorSubject(props)
}
componentDidUpdate() {
this.subject.next(this.props)
}
render() {
return <Sub source={this.subject}>{props => doRender(props)}</Sub>
}
}
}
const Counter = componentFromStream(props$ => {
const { handler: increment, stream: inc$ } = createEventHandler()
const params$ = props$.pipe(
switchMap(props =>
inc$
.pipe(
mapTo(1),
startWith(props.initialValue || 0),
scan((acc, inc) => acc + inc)
)
.pipe(map(count => ({ ...props, count, increment })))
)
)
return params$
// optional: , ({increment, count}) => <div><button onClick={increment}>{count}</button></div>
})
// defaults to render prop component
<Counter initialValue={3}>
{({ increment, count }) => {
return (
<div>
<button onClick={increment}>{count}</button>
</div>
)
}}
</Counter>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment