zanettin/incompose

View on GitHub
src/componentFromStream.js

Summary

Maintainability
A
0 mins
Test Coverage
/**
 * @author recompose (https://github.com/acdlite/recompose)
 */

import { Component } from 'inferno';
import { createChangeEmitter } from 'change-emitter';
import $$observable from 'symbol-observable';
import { config as globalConfig } from './setObservableConfig';

export const componentFromStreamWithConfig = config => propsToVdom =>
    class ComponentFromStream extends Component {
        state = { vdom: null };

        propsEmitter = createChangeEmitter();

        // Stream of props
        props$ = config.fromESObservable({
            subscribe: observer => {
                const unsubscribe = this.propsEmitter.listen(props => {
                    if (props) {
                        observer.next(props);
                    } else {
                        observer.complete();
                    }
                });
                return { unsubscribe };
            },
            [$$observable]() {
                return this;
            },
        });

        // Stream of vdom
        vdom$ = config.toESObservable(propsToVdom(this.props$));

        componentWillMount() {
            // Subscribe to child prop changes so we know when to re-render
            this.subscription = this.vdom$.subscribe({
                next: vdom => {
                    this.setState({ vdom });
                },
            });
            this.propsEmitter.emit(this.props);
        }

        componentWillReceiveProps(nextProps) {
            // Receive new props from the owner
            this.propsEmitter.emit(nextProps);
        }

        shouldComponentUpdate(nextProps, nextState) {
            return nextState.vdom !== this.state.vdom;
        }

        componentWillUnmount() {
            // Call without arguments to complete stream
            this.propsEmitter.emit();

            // Clean-up subscription before un-mounting
            this.subscription.unsubscribe();
        }

        render() {
            return this.state.vdom;
        }
    };

const componentFromStream = propsToVdom =>
    componentFromStreamWithConfig(globalConfig)(propsToVdom);

export default componentFromStream;