Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React JS - What is a good way to handle children click event?

I have a list with around 2k items. If I use onClick on each child, I would end up with 2k listeners which is what I have currently. I would want to do something like making the parent component listen to the click events instead. But if I do that, I don't have reference to the child component which I need to call setState on. Also the list of child components can be filtered dynamically (using this.refs might be bad ?).

The best I can come up with is to make a hash of child components id mapping to child components in the parent and look up the view on click.

Just for illustration purposes:

  var Parent = React.createClass({
      shouldComponentUpdate: function() { return false; },
      handler: function(e) {
         // look up from reference and set state   
      },
      componentWillUnmount: function() {
        // clean up reference   
      },
     render: function() {
       this.reference = {};
       var items = [];
       for(var i = 0; i < this.props.items.length; i++) {
         var child = React.createClass(Child, {id: this.props.items[i].id});
         items.push(child);
         reference[child.id] = child; 
       }
         return React.createClass('div', {onClick: this.handler}, items);
     }
  })

I wonder if there is a React way of dealing with this.

like image 903
Flmhdfj Avatar asked Jun 29 '15 21:06

Flmhdfj


People also ask

How do I prevent a parent's onClick event from firing when a child anchor is clicked?

By a adding an onClick function for the child modal (content div) mouse click events are prevented to reach the 'closeLogin' function of the parent element. This did the trick for me and I was able to create a modal effect with 2 simple divs.

How do parents communicate with children in React?

To do that, I casted the children (received in props by Parent) in to local state. Appended the prop to each child to have a callback function to communicate with the parent. The Parent component now returns the state variable that has the modified / appended props, instead of returns prop. children as it received!


2 Answers

I think this answer may help... It does not matter if you have 2000 event handlers or just one. React deals with it in the same way. Remember that the HTML you return in your render method does not get added to the DOM but it is just used by React to build a virtual DOM representation. In the end, React has only one onClick.

React efficient way to bind event to many dom elements

If you need to know what element triggered the click you just need to access event.target and use any data-attribute to identify the clicked element.

like image 143
damianmr Avatar answered Oct 11 '22 01:10

damianmr


The React way of doing this would be to use a Flux dispatcher + a Store. Basically, you can have each item bind to an event that gets triggered from the store once the store has carried out the tasks you want it to complete.

So the flow will be:

Item gets clicked => Flux event is dispatched => Flux dispatcher hears the events and executes the appropriate function with the data passed from Item component.

  var ItemStore = {
    doSomething: function(data){
      // do something with the data
    }
  }
  MicroEvent.mixin(ItemStore);

  var AppDispatcher = new Dispatcher();

  AppDispatcher.register(function(payload) {

    switch (payload.eventName) {
      case 'item-clicked':
        ItemStore.doSomething(payload.data.someData);
        ItemStore.trigger('did-something');
    }

    return true;

  })


  var Item = React.createClass({
      shouldComponentUpdate: function() { return false; },
      componentDidMount: function() {
        ItemStore.bind('did-something', this.submitHandled);
      },
      handler: function(e) {
        AppDispatcher.dispatch({
          eventName: 'item-clicked',
          data: {
            someData: 'sample data'
          }
        });
      },
      componentWillUnmount: function() {
        // clean up reference   
      },
      submitHandled: function() {
        // do something after the click
      },
     render: function() {
       // insert your item's html here. 
     }
  })
like image 41
Pavan Ravipati Avatar answered Oct 11 '22 03:10

Pavan Ravipati