反应.js从深度嵌套的子元素更改最顶层父元素的状态



我正在使用react-async和node.js。React-async 用于以异步方式使用 react.js。要进行ajax调用,我正在使用超级代理。PostList组件是最顶层的父组件。通过其setTopmostParentState方法,可以更改组件的状态。我想从Comp4调用此方法。此方法的参数将来自使用"超级代理"节点中间件的 ajax 调用。

如何从 Comp4 更改状态?如果是父组件,然后是子组件问题,则可以轻松地将状态更改方法作为prop传递给子组件。但一些嵌套使得很难将参数从深度嵌套的子项传递到最顶层的父项。

代码片段:

    var Comp4 = React.createClass({
      clickHandler: function() {
        request.get('/api/prods_find/' + cat_id + '/' + subcat_id,
          function(resp) {
            var prods_menu = resp.body; 
* * * //CALL setTopmostParentState of the PostList component with the value prods_menu***
          });
      },
      render: function() {
        '<div onClick={this.clickHandler}>Target element</div>'
      }
    });
    var Comp3 = React.createClass({
      render: function() {
        < Comp4 > < /Comp4>
      }
    });
    var Comp2 = React.createClass({
      render: function() {
        < Comp3 > < /Comp3>
      }
    });
    var Comp1 = React.createClass({
      render: function() {
        < Comp2 > < /Comp2>
      }
    });
    var PostList = React.createClass({
      mixins: [ReactAsync.Mixin],
      getInitialStateAsync: function(cb) {
        request.get('http://localhost:8000/api/posts', function(response) {
          cb(null, {
            prods_menu: response.body
          });
        });
      },
      setTopmostParentState: function(prods_menu) {
        this.setState({
          prods_menu: prods_menu
        });
      },
      render: function() {
        var prods = this.state.prods_menu.prods;
        var menu = this.state.prods_menu.menu;
        return (
          < Comp1 > < /Comp1>
        );
      }
    });

在您的特定情况下,我建议传递一个函数,由您最深的子组件调用。

var Comp4 = React.createClass({
      clickHandler: function() {
        request.get('/api/prods_find/' + cat_id + '/' + subcat_id,
          function(resp) {
            var prods_menu = resp.body;
            this.props.updateParentState(prods_menu);
          });
      },
      render: function() {
        '<div onClick={this.clickHandler}>Target element</div>'
      }
    });
    var Comp3 = React.createClass({
      render: function() {
        < Comp4 {...this.props} > < /Comp4>
      }
    });
    var Comp2 = React.createClass({
      render: function() {
        < Comp3 {...this.props} > < /Comp3>
      }
    });
    var Comp1 = React.createClass({
      render: function() {
        < Comp2 {...this.props} > < /Comp2>
      }
    });
    var PostList = React.createClass({
      mixins: [ReactAsync.Mixin],
      getInitialStateAsync: function(cb) {
        request.get('http://localhost:8000/api/posts', function(response) {
          cb(null, {
            prods_menu: response.body
          });
        });
      },
      setTopmostParentState: function(prods_menu) {
        this.setState({
          prods_menu: prods_menu
        });
      },
      render: function() {
        var prods = this.state.prods_menu.prods;
        var menu = this.state.prods_menu.menu;
        return (
          < Comp1 updateParentState={this.setTopmostParentState} > < /Comp1>
        );
      }
    });

但如您所见,这非常麻烦。这就是创建Flux的原因。使用 Flux,您可以将消息分派到包含新数据的存储,存储将通知您的组件,重新渲染它。

您可以在此处了解有关 Flux 的更多信息 https://facebook.github.io/flux/

并不是说它是完美的,但在这种情况下,我正在使用 PubSub 库进行组件通信。例如 https://www.npmjs.com/package/pubsub-js。

在最顶层的组件中,您可以执行以下操作:

var EVENT_NOTIFY_TOPMOST = "EVENT_NOTIFY_TOPMOST";
componentDidMount: function() {
    eventToUnsubscribe = PubSub.subscribe(EVENT_NOTIFY_TOPMOST, function( msg, data ){
        console.log( data ); //logs "world"
    });
}
componentDidUnmount: function() {
    //don't forget this
    PubSub.unsubscribe(eventToUnsubscribe )
}

在你最深的孩子身上,你可以做到这一点:

PubSub.publish(EVENT_NOTIFY_TOPMOST , "world");

最新更新