Reputation: 79
I make simple task for getting job. Working with react and redux. When i get value from input and send them to reducer they are lost in the way. Wait, not so easy. 1st item getting by reducer gets prop name, age, type, index and return new state. Nice. But other items lost prop name and age in the way. What? How did them it? Reducer return empty obj for render. Dont look on obj in dispatch i will rework it.
REDUCER
case 'EDIT_ITEM':
console.log(action.name, action.age, action.id);
return state.map((item, index) =>
action.id === index
? {
name: action.name,
age: action.age
}
: item
);
App.js
function EditUsers() {
const listItems = users.map(function (value, index) {
return (
<form>
<div className="input-group">
<div className="input-group-prepend">
<span className="input-group-text">{value.name}, {value.age}</span>
</div>
<input type="text" placeholder="New name" id="newName" className="form-control"/>
<input type="text" placeholder="New age" id="newAge" className="form-control" aria-describedby="button-addon2"/>
<div className="input-group-append">
<button onClick={() => dispatch({
type: 'EDIT_ITEM',
id: index,
name: document.getElementById('newName').value,
age: document.getElementById("newAge").value
})}
className="btn btn-outline-primary"
type="button"
id="button-addon2">
Изменить
</button>
</div>
</div>
</form>
)
});
return (
<div>{listItems}</div>
)
}
Upvotes: 0
Views: 253
Reputation: 203482
You won't be able to access the input values from the button's onClick
event, but if you decide to leave the inputs uncontrolled and move the logic to the associated form's onSubmit
callback, then you can access the form's field values from the onSubmit
event.
Define a submitHandler
function to consume both the index
and submit event, e
:
const submitHandler = index => e => {
e.preventDefault(); // <-- prevent the default form action, important!
const { newName, newAge } = e.target; // <-- destructure the inputs from the event target
dispatch({
type: "EDIT_ITEM",
id: index,
name: newName.value, // <-- extract the input value
age: newAge.value // <-- extract the input value
});
};
Here the path to the input value is e.target.<fieldId>.value
. Notice I've also defined submitHandler
to curry the index, which allows for more optimal usage when mapping elements.
Next, attach the submitHandler
callback to the onSubmit
prop of the form.
const listItems = users.map(function(value, index) {
return (
<form key={index} onSubmit={submitHandler(index)}>
...
Here the curried function submitHandler(index)
takes the index and encloses it in an instance of the callback, returning a function that takes the onSubmit
event object, e => {...
.
Finally, update the button to have type="submit"
and no onClick
handler.
<button
className="btn btn-outline-primary"
type="submit"
id="button-addon2"
>
Изменить
</button>
Full code
const submitHandler = index => e => {
e.preventDefault();
const { newName, newAge } = e.target;
dispatch({
type: "EDIT_ITEM",
id: index,
name: newName.value,
age: newAge.value
});
};
function EditUsers() {
const listItems = users.map(function(value, index) {
return (
<form key={index} onSubmit={submitHandler(index)}>
<div className="input-group">
<div className="input-group-prepend">
<span className="input-group-text">
{value.name}, {value.age}
</span>
</div>
<input
type="text"
placeholder="New name"
id="newName"
className="form-control"
/>
<input
type="text"
placeholder="New age"
id="newAge"
className="form-control"
aria-describedby="button-addon2"
/>
<div className="input-group-append">
<button
className="btn btn-outline-primary"
type="submit"
id="button-addon2"
>
Изменить
</button>
</div>
</div>
</form>
);
});
return <div>{listItems}</div>;
}
Upvotes: 1