React:使用parent在兄弟组件之间传递数据

时间:2016-02-06 20:49:00

标签: javascript reactjs components

我需要渲染一个widget,它从SettingsPanel接收设置并将它们传递给LayoutPanel(然后根据更新的设置重新渲染自身)。我似乎无法想象一个干净的'这样做的方式。这就是我到目前为止所拥有的:

Widget.js

class Widget extends Component {
    handleSettingsChange() {
        //need to let layout know of change
    }

    render() {
        <div>
            <SettingsPanel
                onSettingsChange={handleSettingsChange}
                initialSettings={this.props.settings}
            />
            <Layout
                data={ this.props.data}
            />
        </div>
    }
}

App.js

const settings = {
    hideImages: true,
    itemsPerPage: 5
}
<Widget settings={ settings } data={ data } />

我的第一个想法是,在Widget中,我可以做到

constructor() {
    super()
    this.setState({ settings: this.props.settings });
}
handleSettingsChange(data) {
    //Assuming data is of the the form {changedProperty: value}
    this.setState({ settings: Object.assign({}, this.state.settings, data) });
}
render() {
    <div>
        <SettingsPanel
            onSettingsChange={handleSettingsChange}
            initialSettings={this.props.settings}
        />
        <Layout
            data={ this.props.data}
            settings={ this.state.settings }
        />
    </div>
}

这样父级是转储消息代理,并且不必知道正在更改哪些特定设置的细节。但是,当然,这不起作用,因为, 一个。我告诉道具设置状态是一种反模式 湾构造函数无论如何都无法访问this.props,并且在其他地方(componentDidMount?)感觉不对。

我的第二个想法是去setProps设置来自父母的孩子的道具,但当然不赞成。

我该如何解决这个问题?我可能会重新设计这个问题,所以这不是一个问题,但坦率地说,我只是想了解我所缺少的东西,或者是什么反应&#39;解决这样的事情的方法是。

This question类似于我遇到的同样问题,但我无法理解/应用已接受的解决方案对我的问题所建议的内容。

tldr; &#34;如何让父组件从一个孩子传递到另一个孩子,同时又不知道它到底是什么?&#34;

2 个答案:

答案 0 :(得分:1)

从道具设置状态不一定是反模式。从构造函数中的props初始化组件的状态似乎是完全合理的。如果有的话,这样做不会降低可测试性或可靠性。

您可以在构造函数中访问props,因为它们作为第一个参数传递。您需要先调用super,然后您可以执行任何您喜欢的操作:

class Widget extends React.Component {
  constructor(props) {
    super(props);
    this.setState({ settings: props.settings });
  }
}

然后你可以沿着你最初走的路走下去。另一个稍微复杂的选择是使用像Redux这样的状态容器为你处理状态管理和转换,但只有在你不介意为你的应用程序设置添加更多内容的额外学习和复杂性时才这样做。

答案 1 :(得分:1)

虽然lukewestby的答案是正确的,因为它解决了原始问题中的问题,经过进一步的反思后,我意识到这是一个错误的问题 - 也就是说,这是一个架构问题,这就是为什么我遇到了实施问题

在这种情况下,数据流是[数据] - &gt;应用 - &gt;小工具 - &gt;儿童。 “App”获取数据,因此App拥有它。小部件不应该能够修改,处理它不拥有的数据的更改。因此,回调需要传递给 grandparent (App),而不是父(Widget)。这就是我最终做的事情。

App.js

 constructor() {
   this.state = { settings: { hideImages: true } };
 }
 handleSettingsChange(data) {
   this.setState({ settings: data });
 }
 render() {
   <Widget settings={ this.state.settings } 
      onSettingsChange={ this.handleSettingsChange }
    />
} 

Widget.js

handleDisplaySettingsChange(data) {
    this.props.onSettingsChange(data);
}
render() {
    return (
        <div>
            <SettingsPanel
                onSettingsChange={ this.handleDisplaySettingsChange }
            />
            <Layout
                {...this.props.settings }
            />
        </div>
    );
}

这样做的好处是设置有一个单一的事实来源,由所有者(App)维护。在原始建议中,如果稍后通过App获取设置已更改,则内部组件将不会收到它(这解释了为什么React docs声称从props设置状态是反模式的原因)