'React - ref Value In onChange in map() That Generate <table> (Meteor)
here is a snippet from render()
{users.map((user)=>{
return <tr key={user._id}>
<td><input onChange={this.handleChange.bind(this, user._id)}
type="text"
ref="name"
value={user.profile.firstName} />
</td>
</tr>
})}
here is the handler:
handleChange(userId) {
console.log(userId);
var name = this.refs.name.value.trim();
console.log(name);
}
The handler will print the correct userId but always the last name in the user table
What is the correct way to create a handler that can fetch the values of the specific input field in a table created by map?
Should I generate unique refs somehow?
Or is there a different method for this one?
Solution 1:[1]
onChange
receives a SyntheticEvent
as a parameter as well. If you add that to your onChange
handler, you can inspect the target and get the new value:
handleChange:
handleChange(userId, event) {
console.log(userId);
var inputElement = event.target;
console.log(inputElement.name + ': ' + inputElement.value);
}
To handle many inputs in a single handleChange
, add standard name
attributes to the inputs and inspect them in the change handler:
{users.map((user)=>{
return <tr key={user._id}>
<td><input onChange={this.handleChange.bind(this, user._id)}
name="name"
type="text"
value={user.profile.firstName} />
</td>
</tr>
})}
This is covered in the controlled components docs.
Solution 2:[2]
Create new component UserListRow.jsx move the code there, e.g.:
{users.map((user)=>{
return <UserListRow user={user} key={user._id}/>
})}
UserListRow.jsx render:
return <tr key={user._id}>
<td><input onChange={this.handleChange.bind(this, user._id)}
type="text"
ref="name"
value={user.profile.firstName} />
</td>
</tr>
move handleChange
to UserListRow.jsx
Solution 3:[3]
I found a solution using the index. You can create an object containing the information you want to update and the item index and set this object on state. Then, on input's value you make a verification between the item index and the object's index you set on state.
here follows and example in typescript and hooks.
interface userNameState {
index: number;
name: string;
}
const [userName, setUserName] = useState({} as userNameState);
the handle change function.
function handleChange(e: FormEvent, index: number) {
let enterEvt = e.target as HTMLButtonElement
const userName = {
index: index,
title: enterEvt.value
}
setUserName(userName)
}
and the map function would something like that
{users.map((user, index)=>{
return <tr key={user._id}>
<td>
<input
onChange={(e) => handleChange(e, index)}
type="text"
value={userName.index === index ? userName.name : user.name} />
</td>
</tr>
})}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Elia Weiss |
Solution 3 | Thiago Padovani |