2

Before anyone press eagerly the close button, I already have looked the following question: ReactJS Two components communicating. My problem is exactly the third scenario developped in the current accepted answer.

I am using ReactJS to build something with two components. For HTML reasons (and presentation), i want my two components to be at two different places of the page.

For the moment, I have the following pattern, corresponding to scenario #2:

FooForm = React.createClass({
    ...
});

FooList = React.createClass({
    ...
});

FooManager = React.createClass({
    ...

    render: function () {
        return (
            <div>
                <FooForm ref="form" manager={this} />
                <FooList ref="list" />
            </div>
        );
    }
});

React.render(
    <FooManager someProp={value} />,
    document.getElementById('foo')
);

This gives something like:

<div id="foo">
     <form>Form generated with the render of FooForm</form>
     <ul>List generated with the render of FooList</ul>
</div>

However, i would like to have something like this:

<div id="fooform">
     <form>Form generated with the render of FooForm</form>
</div>
<!-- Some HTML + other controls. Whatever I want in fact -->
<div>...</div>
<div id="foolist">
    <ul>List generated with the render of FooList</ul>
</div>

The problem here is: how can I keep a reference in each component? Or at least the link Form -> List?

I tried to create the FooList before and pass the reference to the current manager, but I get the following warning/error:

Error: Invariant Violation: addComponentAsRefTo(...): Only a ReactOwner can have refs. This usually means that you're trying to add a ref to a component that doesn't have an owner (that is, was not created inside of another component's `render` method). Try rendering this component inside of a new top-level component which will hold the ref.

The documentation says you can attach events to link two components which do not have a parent-child relation. But I don't see how. Can someone give me some pointers?

Community
  • 1
  • 1
Maxime Lorant
  • 34,607
  • 19
  • 87
  • 97

2 Answers2

3

The Less Simple Communication lesson from react-training has a good example of how you can move actions & state sideways to avoid having to create an explicit link between related components.

You don't need to jump into a full Flux implementation to get the benefit of this approach, but it's a good example to lead you up to Flux, should you eventually need it or something like it.

Note that this requires you to model the relationship between the components based on changing state rather than explicitly passing a reference to a component instance (as you're doing above) or a callback bound to the component managing the state.

Jonny Buchanan
  • 61,926
  • 17
  • 143
  • 150
  • 1
    Exactly what I needed. I have implemented this architecture in 15 minutes with very few changes in my codebase and it works like a charm :) Many thanks. – Maxime Lorant Apr 08 '15 at 12:25
2

This would be the perfect use-case for a Flux type architecture.

What you want is someone FooManager to be able to trigger state changes in both components. Or, in fact, having the different components trigger, through Actions, state changes in each other.

The Flux Todo-App Tutorial illustrates your use-case perfectly!

After this, then you'd have the choices of using Facebooks implementation of Flux or the other gazillion ones. My personal favorite is Reflux

Henrik Andersson
  • 45,354
  • 16
  • 98
  • 92