Link two React component in a backend template

I came accross this situation where I needed one react component to be displayed if a button was clicked. Nothing amazing here. Usually this is easy, make a child component depends on some parent's state. But the button that was toggling the visibility and the form were in different partials in my php views.

I finally got this working doing something like this:

In my backend views

/**
 * view.php
 */
<div data-mount="some-form"></div>

and

/**
 * navbar.php
 */
<li data-mount="toggle-form-button"></li>

Then on the javascript side:

export default function () {
    let someForm = ReactDOM.render(
        <SomeForm />,
        document.querySelector( '[data-mount=some-form]' )
    );

    render(
        <ToggleButton toggleComponent={ someForm } />,
        document.querySelector( '[data-mount=toggle-form-button]' )
    );
}

The trick is to store the return value of ReactDOM.render and pass it to another component. We can then use this reference in the components. The form will toggle its visible state when toggleForm() is called:

// SomeForm.js
constructor( props ) {
    super( props );
    this.state = { visible: false };
    // No need to bind this in the following calls
    this.toggleVisibility = this.toggleVisibility.bind( this );
}

toggleVisibility() {
    this.setState( { visible: !this.state.visible } );
}
// ToggleButton.js
propTypes: {
    toggleComponent: React.PropTypes.object.isRequired,
}

constructor( props ) {
    super( props );
    this.toggleForm = this.props.formElement.toggleVisibility;
}

render() {
    return (
        <div onClick={ this.toggleForm }>
            <div className="btn btn-success cta-button">Toggle form</div>
        </div>
    );
}

I am sure there is a more elegant solution out there in the wild, but I couldn't find it. What first came to me as a simple case got confusing when I started looking at the documentation and couldn't figure this simple thing out... Anyway, this allowed me to mix react components with my backend templates, and that was all I needed.

Published over 2 years ago