Akshay Arora
Akshay Arora

Reputation: 1945

Communicate between two components reactjs

I am making a web application which I intend to make as modular as possible using reactjs.

The application consists of a menu and an associated shopping cart, which keeps a track of what items are put into the cart from the menu.

My code is:

React.render(
                <div className="row">
                <div className="col-md-7">
                    <MainMenu />
                </div>
                <div className="col-md-4">
                <CartView />
                </div>
                </div>
   , mountpoint
    );

As it is visible, there is no hierarchical relationship between my these two components, so clearly I can't communicate by passing props.

I read on the official React documentation:

For communication between two components that don't have a parent-child relationship, you can set up your own global event system. Subscribe to events in componentDidMount(), unsubscribe in componentWillUnmount(), and call setState() when you receive an event. Flux pattern is one of the possible ways to arrange this

However, I do not currently want to use Flux in my application.

So, my question is:

Is there any way of setting up a message passing system between the components without using Flux?

P.S: I know jQuery. I am having trouble understanding the ToDo example given on the Flux website so was just wondering if there is an alternative way of doing this.

Thanks.

Upvotes: 2

Views: 797

Answers (1)

Mike Driver
Mike Driver

Reputation: 8511

Yeah you can do this without Flux. But consider Flux because it's awesome.

But if you don't want to use it, why not make them have a hierarchical relationship?

The way you'll do this is create a new root level component which you mount, which then has the <MainMenu /> and <CartView /> components as children. Provide callbacks for events on these child components which the parent can then bind to to change it's state, which affects the props passed.

An example of this using your code as a base:

var Root = React.createClass({

    getInitialState: function() {
        return {
            itemId: 1
        }
    },

    mainMenuChangeHandler: function(itemId) {
        if (itemId !== this.state.itemId) {
            this.setState({
                itemId: Number(itemId)
            })
        }
    },  

    render: function() {
        return (
            <div className="row">
                <div className="col-md-7">
                    <MainMenu onChange={this.mainMenuChangeHandler} />
                </div>
                <div className="col-md-4">
                    <CartView itemId={this.state.itemId}  />
                </div>
            </div>
        )
    }
});

var MainMenu = React.createClass({
    propTypes: {
        onChange: React.PropTypes.func.isRequired
    },
    clickHandler: function(e) {
        e.preventDefault();
        this.props.onChange(e.target.href);
    },
    render: function() {
        return (
            <div>
                <a href="1" onClick={this.clickHandler}>Item 1</a>
                <a href="2" onClick={this.clickHandler}>Item 2</a>
            </div>
        );
    }
});

var CartView = React.createClass({
    propTypes: {
        itemId: React.PropTypes.number.isRequired
    },
    render: function() {

        var item;
        if (this.props.itemId === 1) {
            item = (
                <div>This is Item 1 being shown</div>
            );
        } else if (this.props.itemId === 2) {
            item = (
                <div>This is Item 2 being shown</div>
            );
        }

        return (
            <div>{item}</div>
        );
    }
});

React.render(<Root />, mountpoint);

Upvotes: 4

Related Questions