How do I set state of sibling components easily in React?

可紊 提交于 2019-12-02 18:05:20

The parent component should pass a callback to the children, and each child would trigger that callback when its state changes. You could actually hold all of the state in the parent, using it as a single point of truth, and pass the "selected" value down to each child as a prop.

In that case, the child could look like this:

var Child = React.createClass({
    onToggle: function() {
        this.props.onToggle(this.props.id, !this.props.selected);
    },

    render: function() {
        return <button onClick={this.onToggle}>Toggle {this.props.label} - {this.props.selected ? 'Selected!' : ''}!</button>;
    }
});

It has no state, it just fires an onToggle callback when clicked. The parent would look like this:

var Parent = React.createClass({
    getInitialState: function() {
        return {
            selections: []
        };
    },
    onChildToggle: function(id, selected) {
        var selections = this.state.selections;

        selections[id] = selected;

        this.setState({
            selections: selections
        });
    },

    buildChildren: function(dataItem) {
        return <Child
            id={dataItem.id}
            label={dataItem.label}
            selected={this.state.selections[dataItem.id]}
            onToggle={this.onChildToggle} />
    },

    render: function() {
        return <div>{this.props.data.map(this.buildChildren)}</div>
    }
});

It holds an array of selections in state and when it handles the callback from a child, it uses setState to re-render the children by passing its state down in the selected prop to each child.

You can see a working example of this here:

https://jsfiddle.net/fth25erj/

Another strategy for sibling-sibling communication is to use observer pattern.

The Observer Pattern is a software design pattern in which an object can send messages to multiple other objects.

No sibling or parent-child relationship is required to use this strategy.

Within the context of React, this would mean some components subscribe to receive particular messages and other components publish messages to those subscribers.

Components would typically subscribe in the componentDidMount method and unsubscribe in the componentWillUnmount method.

Here are 4 libraries that implement the Observer Pattern. The differences between them are subtle - EventEmitter is the most popular.

  • PubSubJS: "a topic-based publish/subscribe library written in JavaScript."
  • EventEmitter: "Evented JavaScript for the browser." It's actually an implementation of a library that already exists as part of nodejs core, but for the browser.
  • MicroEvent.js: "event emitter microlibrary - 20lines - for node and browser"
  • mobx: "Simple, scalable state management."

Taken from: 8 no-Flux strategies for React component communication which also is a great read in general.

The following code helps me to setup communication between two siblings. The setup is done in their parent during render() and componentDidMount() calls.

class App extends React.Component<IAppProps, IAppState> {
    private _navigationPanel: NavigationPanel;
    private _mapPanel: MapPanel;

    constructor() {
        super();
        this.state = {};
    }

    // `componentDidMount()` is called by ReactJS after `render()`
    componentDidMount() {
        // Pass _mapPanel to _navigationPanel
        // It will allow _navigationPanel to call _mapPanel directly
        this._navigationPanel.setMapPanel(this._mapPanel);
    }

    render() {
        return (
            <div id="appDiv" style={divStyle}>
                // `ref=` helps to get reference to a child during rendering
                <NavigationPanel ref={(child) => { this._navigationPanel = child; }} />
                <MapPanel ref={(child) => { this._mapPanel = child; }} />
            </div>
        );
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!