Passing props down from createContainer to child components


#1

I have a React container which collects data, then passes it (and props) to a React component and so on. How do I get props from the higher level container/components into lower level container/components:

In this example, I have a locale field in the records of the UsersExtraColl collection that I want passing all the way down to the ListTable component:

Flowrouter.route('/', {
    action: function(params, queryParams) {
        ReactLayout.render(AppWrapperLoggedInContainer, {content: <List />});
    }
});

AppWrapperLoggedInContainer:

export default createContainer(({ params }) => {
    const dataHandle = Meteor.subscribe('UsersExtraPub');
    const dataIsReady = dataHandle.ready();
    return {
        dataIsReady,
        data: dataIsReady ? UsersExtraColl.find().fetch() : []
    };
}, AppWrapperLoggedIn);

AppWrapperLoggedIn:

export default class AppWrapperLoggedIn extends React.Component {

    constructor(props) {
        super(props);
    }

    render(){
        if (!this.props.dataIsReady) {
            return (
                <div>
                    <div>Loading...</div>
                </div>
            )
        }
        else {
            return (
                     <div>
                     ...
                     {this.props.content}
                     ...
                     </div>
            )
        }
    }
}

List:

export default class List extends React.Component {

    render(){
        return (
           <div>
               <ListTableContainer />
           </div>
        )
    }
}

ListTableContainer:

export default createContainer(({ params }) => {
    const dataHandle = Meteor.subscribe('ListsPub');
    const dataIsReady = dataHandle.ready();
    return {
        dataIsReady,
        data: dataIsReady ? ListsColl.find().fetch() : []
    };
}, ListTable);

ListTable:

export default class ListTable extends React.Component {
    console.log(this.props){
    render(){
        ...
    }
}

In ListTable, this.props does not contain the locale information.


#2

There currently isn’t a great way to pass data from the layout into the child. I’d suggest doing the UsersExtraColl.find().fetch() again inside ListTableContainer.

Alternatively, you can do something like this: http://jaketrent.com/post/send-props-to-children-react/ but that seems a bit more complicated than the simple answer of just adding the query to the container.


#3

Thanks sashko. It kinda feels like React should facilitate an easy way to pass properties down the component tree. I haven’t done much reading arounf Flux annd sotres, but do you know if they would server this purpose?

Does the second fetch cause significant inefficientices/slowness if this method is scaled up?

Do you know if Blaze would be better suited to handlng this?


#4

I think the idea of flux is to do the data fetching in the container where you need it, so my suggestion of doing another query is actually exactly the most fluxy way to do it. In the flux model you never pass callbacks up and down the tree, you just put the data in a global store (minimongo) and query where you need it (the container).

I don’t think what I suggested would cause inefficiencies.


#5

What about React’s getChildContext? I’ve just played with it a few days ago. With childContext you can pass values down to all children components.


#6

I think people have mentioned that context is on the path to deprecation eventually. So it might be good to limit its use unless it’s absolutely necessary.


#7

I’m upgrading a react app to the containers approach and have run into the same problem. I have to replace getChildContext with an approach where context chains to descendants. I was curious how you resolved it.


#8

I ended up using <MyComponent {…this.props} />. I started off using React clone element thiny, but simply re-structure my app to not use it in the end. I realised that props passed through the createContainer block reach the destination component, so you can use <MyComponent {…this.props} /> to pass the props down into child components.