Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React: Retrieve dynamic child key upon event

I am aware that dynamic children of a component must have a unique key as the following (modified example from official docs):

render: function() {
  var results = this.props.results;
  return (
    {results.map(function(result) {
      return <ChildComponent type="text" key={result.id} changeCallback={this.props.callbackFn}/>;
    })}
  );
}

Considering that ChildComponent is another React component nested here, with a render method as bellow

render: function() {
  var results = this.props.results;
  return (
    <div className="something">
       <input type="text" onChange={this.props.changeCallback} />
    </div>
  );
}

is there any way to access the key when callbackFn(event) is called?

like image 574
Yan Foto Avatar asked May 03 '14 19:05

Yan Foto


People also ask

How do I get the React key from an event?

To get the key index of an element on click in React:Add an onClick event listener to each element. Every time an element is clicked, call the handler function passing it the event and the key index.

How do you access child elements in React?

In React we can access the child's state using Refs. we will assign a Refs for the child component in the parent component. then using Refs we can access the child's state. Creating Refs Refs are created using React.

How do you trigger event from parent to child component in React?

Just call an alert method in the childToParent function and pass that function as a prop to the child component. And in the child component, accept the childToParent function as a prop. Then assign it to an onClick event on a button. That's it!

How do I get onClick to child React?

To pass an onChange event handler to a child component in React: Define the event handler function in the parent component. Pass it as a prop to the child component, e.g. <Child handleChange={handleChange} /> . Set it to the onChange prop on the input field in the child.


3 Answers

Although the first answer is correct this is considered as a bad practice since:

A bind call or arrow function in a JSX prop will create a brand new function on every single render. This is bad for performance, as it will result in the garbage collector being invoked way more than is necessary.

Better way:

var List = React.createClass({
  handleClick (id) {
    console.log('yaaay the item key was: ', id)
  }

  render() {
    return (
      <ul>
        {this.props.items.map(item =>
          <ListItem key={item.id} item={item} onItemClick={this.handleClick} />
        )}
      </ul>
    );
  }
});

var ListItem = React.createClass({
  render() {
    return (
      <li onClick={this._onClick}>
        ...
      </li>
    );
  },
  _onClick() {
    this.props.onItemClick(this.props.item.id);
  }
});

Source: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md

like image 101
barczag Avatar answered Oct 16 '22 18:10

barczag


Partially apply the function callback by using JavaScript's native bind. This is mentioned in React's "Communicate Between Components" doc:

callbackFn: function(key) {
  // key is "result.id"
  this.props.callbackFn(key);
},
render: function() {
  var results = this.props.results;
  return (
    <div>
      {results.map(function(result) {
        return (
          <ChildComponent type="text" key={result.id}
            changeCallback={this.callbackFn.bind(this, result.id)} />
        );
      }, this)}
    </div>
  );
}
like image 32
Ross Allen Avatar answered Oct 16 '22 16:10

Ross Allen


We can access data with Data Attributes

// ChildComponent.js
render: function() {
  var results = this.props.results;
  return (
    <div className="something">
       <input 
          type="text" 
          onChange={this.props.changeCallback} 
          data-key={this.props.key} // "key" was passed as props to <ChildComponent .../>
       />
    </div>
  );
}

Now; in your changeCallback method; you can access this data:

// ParentComponent.js
(evt) => {
  console.log(evt.target.dataset.key);
}

Good Luck...

like image 1
Aakash Avatar answered Oct 16 '22 16:10

Aakash