Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Externally injected content with ES6 Class-based components #4087

Closed
quantizor opened this issue Jun 10, 2015 · 6 comments
Closed

Externally injected content with ES6 Class-based components #4087

quantizor opened this issue Jun 10, 2015 · 6 comments

Comments

@quantizor
Copy link
Contributor

I have a use case where I am creating a UIPane element in one place (a window manager), passing its reference to an application bootstrapper and then the application is responsible for injecting other elements into its UIPane.

Since the setProps-esque methods were removed for ES6 classes, how can I accomplish this?

// uiPaneElement (instance of UIPane) is created and rendered, reference is passed back
windowManager.createWindow().then(function(uiPaneElement) {
    MyApp.mount(uiPaneElement);
});

// MyApp.mount - somewhere else in the system
function(uiPaneElement) {
    uiPaneElement.setProps({
        children: this.content
    });
}
@sophiebits
Copy link
Collaborator

If you really want to control the children of UIPane imperatively in that way, you can add a setChildren method to the instance that can be called from outside which updates its state. (Or you could do the same on a wrapper component.) Something like:

class UIPane extends React.Component {
  setChildren(children) {
    this.setState({children: children});
  }
  render() {
    return <div>{this.state.children}</div>;
  }
}

(setProps in particular can be confusing because now you have multiple places in your app disagreeing about what they think the current props are.)

@jimfb also has a ReactComponentRenderer wrapper class that might be helpful. Like #1711.

@quantizor
Copy link
Contributor Author

@spicyj Thank you very much for the lightning reply!

@quantizor
Copy link
Contributor Author

@spicyj I tried your suggestion and the class method doesn't seem to be available on the ReactElement.

class UIPane extends UIView {
    constructor(...args) {
        super(...args);

        this.state = {
            children: null
        };

        this.setChildren = this.setChildren.bind(this);
    }

    componentWillUnmount() {
        if (this.props.handleUnmount) {
            this.props.handleUnmount();
        }
    }

    setChildren(renderables) {
        return new Promise((resolve) => {
            this.setState({
                children: renderables
            }, resolve);
        });
    }

    render() {
        return (
            <div className='ui-pane'>
                {this.state.children}
            </div>
        );
    }
}

Later on, uiPane.setChildren() doesn't exist though

@zpao
Copy link
Member

zpao commented Jun 11, 2015

This should work:

var uiPane = React.render(<UIPane ... />, node)
uiPane.setChildren(stuff)

You'll have a component instance, not an element. You can't do anything with just an element (<UIPane/>) except render it.

@sophiebits
Copy link
Collaborator

You can also do

<UIPane ref="pane" />

and then this.refs.pane.setChildren().

@quantizor
Copy link
Contributor Author

quantizor commented Jun 11, 2015 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants