Frage

The standard way for a React component to include child components is to create them in the render method and set to the children property. In my use case, children may be created before the parent is rendered and passed in through the parent's properties.

Events in the child are bubbled up to the parent as expected, but changes to the parent container do not re-render children created this way. The docs indicate that there is a difference between parent and owner relationships, the latter being established only for components created in render, so my guess is this relationship is missing and important for cascading re-renders.

Here is a simple example (fiddle)

 /** @jsx React.DOM */

globalState = 'initial state';

var Child = React.createClass({
    render: function() {
        return React.DOM.input({
            value:globalState
        });
    }
});

var Parent = React.createClass({
    handleChange: function(e) {
        globalState = e.target.value;
        this.forceUpdate();
    },
    render: function() {
        return React.DOM.div({
            children: [
                Child(),
                React.DOM.br(),
                this.props.passedChild
            ],
            onChange: this.handleChange
        });
    }
});

c = Child();
p = Parent({passedChild:c});

React.renderComponent(p, document.body);

In this example, both child inputs can be edited, the onChange event is caught by the parent and a forceUpdate() is called. This does cascade down to the first child which is created in the render method, but not to the second child which is created elsewhere and passed in.

How can I update the owner of a child component so it will update as desired?

My backup plan is to wire up an event listener on child components. In my application, there is quite a bit of logic around when components are created that would make it impractical to do everything in render().

War es hilfreich?

Lösung

This is slightly complex to explain here, but your code will now work on the master build of React (post 0.10.0).

I'm not too sure what you're trying to accomplish here, but if you change your this.props.passedChild to this.props.passedChild() and c = Child(); to c = Child;, it'll work. Call it this.props.passedChildClass or something. You can also try this.props.passedChildFn with c = function() { return Child(); }. Whatever suits your need.

Don't create an instance of a component and pass it around (it won't be a big problem anymore soon; the return value of Child() won't be an instance anymore). In general it's bad practice because this encourages mutation. Create your children on the fly as you need them and let React handle the rest.

In my application, there is quite a bit of logic around when components are created that would make it impractical to do everything in render().

Break them into helper functions! You really don't have to stuff everything into a single render.

Also, global state is a bad idea. The fact that your child updates correctly by reading from globalState is very fragile. You must have gotten a warning in your console (providing you're using the dev build) to add an onChange handler. Go read it =).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top