Response.js changes the state of the topmost parent from a deeply nested child

I am using react-async along with node.js. React-async is used to consume response.js in an asynchronous way. To make ajax calls, I am using a super agent . The component PostList

is the top-most parent component. Thanks to its method, the setTopmostParentState

state of the component can be changed. I want to call this method from Comp4

. The parameter to this method will be obtained from the ajax call using the "super-agent" node middleware.

How can I change the state from Comp4? If it was a parent component and then a child component issue, then the state change method can easily be passed as a prop

child component. But multiple nesting makes it difficult to pass a parameter from a deeply nested child to the topmost parent.

Snippet of code:

    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>

        );
      }

    });

      

+3


source to share


2 answers


In your specific case, I would suggest passing in a function that your deepest child component should call.

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>

        );
      }

    });

      



But as you can see, this is rather cumbersome. This is why Flux was created. Using Flux, you can send a message to the Store containing the new data and the Store will notify your component by re-executing it.

You can read more about Flux here https://facebook.github.io/flux/

0


source


Not to say that this is great, but in a situation like this I use the PubSub library to link components. For example https://www.npmjs.com/package/pubsub-js .

In your top component, you can do this:

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 )
}

      



And in your deepest child, you can do this:

PubSub.publish(EVENT_NOTIFY_TOPMOST , "world");

      

0


source







All Articles