Skip to content

making Flux.createContainer component #25

@lelandrichardson

Description

@lelandrichardson

Hey @kjda,

I made a "Container" component the other day that's meant to work with ReactFlux, and thought I'd shoot it over to you in case you thought this could be part of the core library, or if you had any suggestions.

My implementation is as follows:

/*
    Example Usage:
    ==============

    var IssueSearchContainer = Flux.createContainer(IssueSearch, {
        mixins: [ IssueStore.mixin() ],
        getComponentProps() {
            return {
                issues: IssueStore.getIssues(this.props.params.page)
            };
        },
        loadingComponent: <Loading />
    });



    Spec Options:
    =============

    getComponentProps: (required)
        method to return the props passing to the child container. This
        is likely where you will access stores.

    loadingComponent: (optional)
        component to render while container is in the "loading" state.

    isLoading: (optional)
        method that returns a boolean of whether or not the component is
        in a loading state or not. If not provided, it will simply check
        for `null` or `undefined` props being passed to the component.

    ...React.Component options
        the spec is passed into the Container component as a mixin, so any
        lifecycle methods you want to attach here will work.

*/


var Container = {
    create(Component, spec) {
        return React.createClass({
            mixins: [spec],

            // for when you want to access the "pure" component, ie for testing
            Component,

            getState() {
                var $props = this.getComponentProps();

                var $loaded = true;
                if (this.isLoading) {
                    $loaded = this.isLoading();
                } else {
                    for (var prop in $props) {
                        if ($props[prop] === null || $props[prop] === undefined) {
                            $loaded = false;
                        }
                    }
                }

                return { $props, $loaded };
            },

            getInitialState() {
                return this.getState();
            },

            getStateFromStores() {
                return this.getState();
            },

            render() {
                if (!this.state.$loaded) {
                    if (this.renderLoading) {
                        return this.renderLoading();
                    } else if (this.loadingComponent) {
                        return this.loadingComponent;
                    } else {
                        return null; // don't render anything...
                    }
                }

                return (
                    <Component
                        {...this.props}
                        {...this.state.$props}
                    />
                );
            }
        })
    }
};

module.exports = Container;

If you think it would be a good addition, I can whip up a PR with some tests and have it exposed as Flux.createContainer or something like that.

A similar concept exists in several other flux libraries:

http://alt.js.org/docs/components/altContainer/
http://acdlite.github.io/flummox/docs/api/fluxcomponent

And then here's a blog post that might explain some of the concepts:

https://medium.com/@learnreact/container-components-c0e67432e005

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions