Reputation:
My React render function eventually renders a set of elements:
data.map((element) => {
return <Object onChange={this.onObjectChange} />;
});
My question is what is the appropriate way to figure out which object had its onChange
method called when I receive the callback?
Upvotes: 5
Views: 4666
Reputation: 1223
To avoid creating an anonymous function in every render, you could have a function that creates the handlers like this (I am using Todo App as an example):
createOnChangeEventHandler(todo) {
const { onToggleClick } = this.props;
this.handlers = this.handlers || {};
if (!this.handlers[todo.id]) {
this.handlers[todo.id] = () => onToggleClick(todo.id);
}
return this.handlers[todo.id];
}
...
Then in render()
{todos.map(todo => (<Todo key={todo.id} onClick={this.createOnChangeEventHandler(todo)} />))}
Upvotes: 0
Reputation: 1120
If you can, pass the ID or element to the component you're creating, then pass that reference back to your event handler.
handleObjectChange = id => {
const object = data.find(id)
}
render() {
return data.map((element, index) => (
<Object onChange={this.handleObjectChange} key={element.id} id={element.id} />
))
// or just pass element={element} to track the object itself, why not?
// after all, every array item's key must be unique
}
In Object...
function change() {
const { onChange, id } = this.props
onChange(id)
}
Is your Object closed, or prefer not to add an extra property? You could try wrapping it.
class IdentifiedButton extends Component {
handleClick = (event, ...args) => {
const { id, onClick } = this.props
onClick(event, id, ...args)
}
render() {
const { id, onClick, ...props } = this.props
return <Button onClick={this.handleClick} {...props} />
}
}
Upvotes: 1
Reputation: 328
If rerendering your Object
component won't cost you that much I would go with something like this
data.map(element => <Object onChange={() => this.onObjectChange(element)} />);
If Object
component is quite heavyweight you better pass element
to Object
component and then pass it to onChange
callback
data.map(element => (
<Object
key={element.id}
onChange={this.onObjectChange}
element={element}
/>
);
class Object extends React.Component {
handleChange = () => this.props.onChange(this.props.element)
render(){
return (
<input type='text' onChange={this.handleChange} />
)
}
}
Upvotes: 0
Reputation: 42450
Wrap the callback in a function and pass an identifier:
data.map(element => <Object onChange={event => this.onObjectChange(element.id, event)} />);
Upvotes: 0
Reputation: 10714
The first parameter to the onSubjectChange
function will have your event which contains the event information.
Hope that helps!
Upvotes: 1