Behaviour of createContainer


#1

I have a Meteor/React application and am using the Meteor createContainer container method to collect data from Mongo and pass the results into a child component. I am finding that when any of the params change, the Mongo query re-computes (even though the params do not affect the Mongo query itself) and the props are sent onto the child component which causes it to re-render unecessarily. Is this the way createContainer is supposed to work, or should it simply just send down props only when the data that is returned by the query changes?

export default MyComponentContainer = createContainer(( params ) => {

    // Some Mongo queries...
    var query results = MyColl.find({}).fetch();

    return {
        query results  
    };

}, MyComponent);

#2

The behavior is correct. React doesn’t know that you aren’t using the parameters to pass down updated information to MyComponent. You can stop the flow of those updates, however, by using React Component lifecycle hooks. Check out the following link for more information:

You could either implement that on MyComponent itself, or insert another Higher Order Component between createContainer and MyComponent.


#3

Isn’t this counter-intuitive to React principle? For example, if I have param1 and param2 passed to createContainer, then param1 changes (via an action from a parent component) and this causes all Mongo database calls to be re-run?


#4

I have a component with a form on it, which contains a few input(text) elements and a select element. When the component receives it’s data from createContainer if will set the components state with the values of the form fields, so that they receive the necessary values. However, whilst the user is entering information into the input fields, I do not want the component updating because this will overwrite what the user has typed. I cannot use shouldComponentUpdate because this will prevent the whole form from being updated and I still want the select element to be auto-updated. SO how do I get around this?

See: http://stackoverflow.com/questions/40573228/how-to-prevent-individual-form-elements-from-updating-using-meteor-react


#5

Just because the form re-renders doesn’t mean that its state should be lost. You should be using controlled components (https://facebook.github.io/react/docs/forms.html) and either store the state inside of the form component itself using this.setState whenever an input changes, or in a parent component somewhere (like in a reactive dict maintained by the createContainer function, but initialized outside of its reactive function), or using a redux-like store. Then, when your form re-renders, the values stored in your forms persist, and naturally get re-rendered along with the form’s inputs themselves.


#6

Thanks for these suggestions. As the data coming in from createContainer can arrive after the component has mounted, I use the following pattern to update the input (text) element value:

componentWillReceiveProps(nextProps) {
    this.setState({name: (nextProps.name) ? nextProps.name : ""});
}

Is this the recommended way to do this? If so, then going back to the original issue, am I correct in saying that the only way to solve this using the above method is to add in some conditional logic to not update the state of the element when the props update:

if( !this.state.formDataLoaded ){
    this.setState({name: (nextProps.name) ? nextProps.name : ""});
    this.setState({formDataLoaded: true});
}