Dynamically adding input elements to form in react - arrays

I am trying to dynamically add state to an array from my form in such a way that multiple inputs can eventually be saved as state in the same array, much like the redux form but I don't know Redux yet.
I don't know how to access the current array I am in so I can set the current input value as state. In this case, I am trying to save the name of the ingredient inside the ingredient array within the recipe state by mapping over the current array. Problem is when I try to map over the current array it apparently isn't an array at all and I get the following error when I try to enter data into the input..
TypeError: currentIngredients.map is not a function
(anonymous function)
src/components/recipes/Recipe_Form.js:68
65 | <input
66 | onChange={e => {
67 | const name = e.target.value;
> 68 | setRecipe((currentIngredients) =>
| ^ 69 | currentIngredients.map(x =>
70 | x.id === i.id
71 | ? {
. I am unsure how to access the ingredient array in such a way that I can edit state.
thanks
export const Recipe_Form = () => {
const recipeContext = useContext(RecipeContext);
const [recipe, setRecipe] = useState({
title: "",
img: "",
ingredients: [{ id: "1", name: "cheese", amount: "200" }],
method: "",
serves: "",
time: "",
});
const onChange = (e) =>
setRecipe({ ...recipe, [e.target.name]: e.target.value });
const onSubmit = (e) => {
e.preventDefault();
recipeContext.addRecipe(recipe);
setRecipe({
title: "",
img: "",
ingredients: [],
method: "",
serves: "",
time: "",
});
};
const { title, img, ingredients, method, serves, time } = recipe;
return (
<div className='row center-align'>
<form className='col s12' onSubmit={onSubmit}>
{/* Image */}
<div className='input-field col s12 center-align'>
<input
type='text'
placeholder='Please enter an image url'
name='img'
value={img}
onChange={onChange}
/>
</div>
{/* Title */}
<div className='input-field col s12 center-align'>
<input
type='text'
placeholder='Please enter recipe title'
className='validate'
name='title'
value={title}
onChange={onChange}
/>
</div>
{ingredients.map((i) => {
return (
<div key={i.id}>
<input
onChange={(e) => {
const name = e.target.value;
setRecipe((currentIngredients) =>
currentIngredients.map((x) =>
x.id === i.id
? {
...x,
name,
}
: x
)
);
// e.target.value
}}
value={i.name}
placeholder='ingredient'
/>
<input value={i.amount} placeholder='amount' />
</div>
);
})}
{/* Method */}
<div className='methodContainer'>
<div className='row method-line'>
<div className='input-field col s12 center-align'>
<input
type='text'
placeholder='Please enter method'
className='validate'
name='method'
value={method}
onChange={onChange}
/>
</div>
</div>
</div>
<a className='btn-floating btn-large waves-effect waves-light red'>
<i className='fas fa-plus'></i>
</a>
{/* Serves */}
<div className='input-field col s12 center-align'>
<input
type='number'
placeholder='Number of servings'
className='validate'
name='serves'
value={serves}
onChange={onChange}
/>
</div>
{/* Time */}
<div className='input-field col s12 center-align'>
<input
type='text'
placeholder='Time to compelete...'
className='validate'
name='time'
value={time}
onChange={onChange}
/>
</div>
<br></br>
<button
className='btn waves-effect waves-light'
type='submit'
name='action'>
Submit
</button>
</form>
</div>
);
};
export default Recipe_Form;

Isn't this, because the currentIngredients is actually your state object? you don't have to use it that way. You can do something like that:
setRecipe({
...recipe,
ingredients: recipe.ingredients.map(x =>
x.id === i.id
? {
...x,
name
}
: x
)
});

Related

How to get different data from a dynamically render input field react js

I have state,
const [state, setState] = useState({
semester: '',
credit: '',
sgpa: ''
})
I have taken an input field where user can give his value.According to the user input dynamicallyinputfield will be created.So here my issue is 'I want different data from each dynamically created field'.How can I achive that?
Screenshot of form
my whole component is,
import React, { useState } from "react";
import cal from "./image/bgimg.jpg";
function Home() {
const [state, setState] = useState({
semester: "",
credit: "",
sgpa: "",
});
const [noOfSem, setNoOfSem] = useState([]);
const handleChange = (e) => {
setState({ ...state, [e.target.name]: e.target.value });
};
const handleClick = () => {
let sems = [];
for (let index = 0; index < state?.semester; index++) {
sems.push(index + 1);
}
console.log(sems);
setNoOfSem(sems);
};
const emptySemester = () => {
setState({ ...state, semester: "" });
setNoOfSem([]);
};
const handleCgpaSubmit = () => {
console.log(state.credit, state.sgpa);
};
return (
<div className="container">
<div className="row">
<div className="col-md-6">
<img src={cal} alt="" className="imgcal img-fluid" />
</div>
<div className="col-md-6">
<div className="col-md">
<div className="form1">
<div className="col-md formmain">
<input
type="number"
value={state?.semester}
name="semester"
onChange={handleChange}
placeholder="Enter Total Semester"
/>
{noOfSem.length === 0 ? (
<button
type="button"
className="btn btn-success btn333"
onClick={handleClick}
>
Submit
</button>
) : (
<button
type="button"
className="btn btn-success btn333"
onClick={emptySemester}
>
Reset Semester
</button>
)}
</div>
<div className="col form2">
{noOfSem?.map((item, index) => (
<>
<div className="col-md seminpt">
<label htmlFor="">Semester {index + 1}</label>
<input
type="Number"
name="credit"
value={state.credit}
onChange={handleChange}
placeholder="Total Credit"
/>
<input
type="Number"
name="sgpa"
value={state.sgpa}
onChange={handleChange}
placeholder={`SGPA sem${index + 1}`}
/>
</div>
</>
))}
{noOfSem.length > 0 && (
<button
type="button"
className="btn btn-success btn3334"
onClick={handleCgpaSubmit}
>
Submit
</button>
)}
</div>
</div>
</div>
</div>
</div>
</div>
);
}
export default Home;
'I want different data from each dynamically created field'.How can I achive that?
Thanks in advance....
I changed the input for the number of semester to have a ref, since there is no need to update a state everytime you change the input. When calling handleClick it will take the value of the input and update noOfSem.
The handleChange takes in a semester index, this will help keep track of which data belongs to which semester. We return a new state with and override the prevState on the given semesterIndex.
When rendering the we just create a new array the size of noOfSem. Getting the values from the state we simply pass in the semesterIndex and pick the property we want.
function Home() {
const [state, setState] = useState({});
const [noOfSem, setNoOfSem] = useState(0);
const semesterNumberInputRef = useRef(null);
const handleChange = (e, semesterIndex) => {
setState((prevState) => {
return {
...prevState,
[semesterIndex]: {
...prevState[semesterIndex],
[e.target.name]: e.target.value,
},
};
});
};
const handleClick = () => {
if (!semesterNumberInputRef.current) return;
const newNumberOfSemesters = Number(semesterNumberInputRef.current.value);
setNoOfSem(newNumberOfSemesters);
};
const emptySemester = () => {
setState({});
setNoOfSem(0);
};
const handleCgpaSubmit = () => {
console.log(state);
};
return (
<div className="container">
<div className="row">
<div className="col-md-6">
<div className="col-md">
<div className="form1">
<div className="col-md formmain">
<input
ref={semesterNumberInputRef}
type="number"
name="semester"
placeholder="Enter Total Semester"
/>
{noOfSem === 0 ? (
<button
type="button"
className="btn btn-success btn333"
onClick={handleClick}
>
Submit
</button>
) : (
<button
type="button"
className="btn btn-success btn333"
onClick={emptySemester}
>
Reset Semester
</button>
)}
</div>
<div className="col form2">
{new Array(noOfSem).fill(null).map((_, index) => {
const semesterIndex = index + 1; // add one since the index starts at 0
return (
<div
className="col-md seminpt"
key={`semester-input-${index}`}
>
<label>Semester {index + 1}</label>
<input
type="number"
name="credit"
value={state[semesterIndex]?.credit || ""}
onChange={(e) => handleChange(e, semesterIndex)}
placeholder="Total Credit"
/>
<input
type="number"
name="sgpa"
value={state[semesterIndex]?.sgpa || ""}
onChange={(e) => handleChange(e, semesterIndex)}
placeholder={`SGPA sem${semesterIndex}`}
/>
</div>
);
})}
{noOfSem > 0 && (
<button
type="button"
className="btn btn-success btn3334"
onClick={handleCgpaSubmit}
>
Submit
</button>
)}
</div>
</div>
</div>
</div>
</div>
</div>
);
}
handleCgpaSumbit will log this as result, an object with the number of the semester as index and the according data.
{
"1": {
"credit": "20",
"sgpa": "10"
},
"2": {
"credit": "21",
"sgpa": "9"
},
"3": {
"credit": "13",
"sgpa": "6"
},
"4": {
"credit": "8",
"sgpa": "6"
}
}
I hope this helps you with your project!

ReactJS How to update the state in object which is in the array

Hello I have one problem that I don't know ho to solve.
I have simple formular where the user type som inputs. After that when he clicks on the Button the firstName, lastname and picture will be display under the formular. And when I click on the input it will show the address and date.
But I have problem to do that. In App.js I have a state which initialli si empty array and after click on submit button the user inputs is added to this empty array. In Suggestions.js I map the sugestions array for displaying every suggestion from the user.
In UserInputs.js I have a state where I add into state a 'visible' to false and I want to do, when I clicked on on suggestion in a list it will display the description and date below this particular sugestion.
I want to do it like this. In App.js
const detail = (suggestion) => {
setSuggestions([...suggestions]); //but I don't know how to set state for particular
suggestion in the array.
};
My code:
App.js
import React, { useState } from "react";
import Suggestions from "./components/Suggestions";
import UserInputs from "./components/UserInputs";
function App() {
const [suggestions, setSuggestions] = useState([]);
const addNewSuggestion = (suggestion) => {
setSuggestions([suggestion, ...suggestions]);
};
const detail = (suggestion) => {
setSuggestions([...suggestions]);
};
console.log("suggestions", suggestions);
return (
<div className="app-container">
<UserInputs addNewSuggestion={addNewSuggestion}></UserInputs>
<Suggestions suggestions={suggestions} detail={detail}></Suggestions>
</div>
);
}
export default App;
Suggestions.js
import React from "react";
export default function Suggestions({ suggestions, detail }) {
return (
<div className="suggestion-container">
<h1 className="suggestion-heading">Zoznam Podnetov</h1>
{suggestions.map((suggestion, index) => {
return (
<div
key={suggestion.id}
className="suggestion"
onClick={() => detail(suggestion)}
>
<div className="suggestion-number">{index + 1}</div>
<div className="suggestion-details">
<div className="suggestion-name">
{suggestion.firstName}
{` ${suggestion.lastName}`}
</div>
<div className="suggestion-address">{suggestion.address}</div>
{suggestion.visible ? (
<div className="suggestion-description">
<p>{suggestion.description}</p>
<p>Podnet bol pridaný: {suggestion.date}</p>
</div>
) : null}
</div>
<div className="suggestion-picture">
<img
src={suggestion.picture}
alt="obrázok"
className="suggestion-picture"
></img>
</div>
</div>
);
})}
</div>
);
}
Userinputs.js
import React, { useState } from "react";
export default function UserInputs({ addNewSuggestion }) {
const randomId = Math.floor(Math.random() * 1000000);
const [userInputs, setUserInputs] = useState({
id: randomId,
firstName: "",
lastName: "",
address: "",
description: "",
picture: null,
date: new Date().toLocaleDateString(),
visible: true,
});
const onInputChange = (event) => {
setUserInputs({
...userInputs,
[event.target.name]: event.target.value,
});
};
const fileSelectHandler = (event) => {
setUserInputs({
...userInputs,
picture: URL.createObjectURL(event.target.files[0]),
});
};
const onSubmit = (event) => {
event.preventDefault();
addNewSuggestion(userInputs);
setUserInputs({
id: randomId,
firstName: "",
lastName: "",
address: "",
description: "",
picture: null,
date: new Date().toLocaleDateString(),
visible: true,
});
};
return (
<div>
<form className="form-container">
<div className="row">
<label>Meno</label>
<input
autoFocus
type="text"
name="firstName"
value={userInputs.firstName}
onChange={onInputChange}
></input>
</div>
<div className="row">
<label>Priezvisko</label>
<input
type="text"
name="lastName"
value={userInputs.lastName}
onChange={onInputChange}
></input>
</div>
<div className="row">
<label>Adresa</label>
<input
type="text"
name="address"
value={userInputs.address}
onChange={onInputChange}
></input>
</div>
<div className="row">
<label>Popis</label>
<input
type="text"
name="description"
value={userInputs.description}
onChange={onInputChange}
></input>
</div>
<div className="row">
<input type="file" onChange={fileSelectHandler}></input>
</div>
<button onClick={onSubmit} className="button">
Odoslať
</button>
</form>
</div>
);
}
Thank you very much for your help.
you can update the suggestion, where the id matches input suggestion and only update it. Please find the code below:
const detail = (suggestion) => {
let tempSuggestions = suggestions.map( (item) => {
if(item.id === suggestion.id) return suggestion
return item
})
setSuggestions([...tempSuggestions]);
}

Adding new objects multiple values to list using UseState & form ReactJS

I've been trying to create a form that can add a list of objects with multiple attributes to a list. I managed to get this right with one string attribute. But, I cannot figure out how to add an entire object with property values passed from the form. I'm using functional components to do this........How can I create a form that adds new objects of items to a list? I'm fairly new to ReactJS, btw.
resume.jsx
function App() {
const [jobExperience, setjobExperience] = useState([{
jobCompanyName: '',
jobDateRangeStart: '',
jobDateRangeEnd: '',
jobDescription: '',
reference_up_count: 0,
reference_down_count: 0,
}]);
const refUpvoteCount = index => {
const newReferences = [...jobExperience];
newReferences[index].reference_upvote_count++;
setjobExperience(newReferences)
}
const refDownvoteCount = index => {
const newReferences = [...jobExperience];
newReferences[index].reference_downvote_count++;
setjobExperience(newReferences)
}
return(
<Container className="container-fluid g-0">
<Row>
<Col>
<div>
{jobExperience.map((jobExp, index) => (
<JobExperience key={index} jobExperience={jobExp} refUpvote={refUpvoteCount} refDownvote={refDownvoteCount}
))}
</div>
</Col>
<Col>
<div className="pl-5 pr-5 pb-2">
<form onSubmit={//Add To Array of item Objects}>
<div className="form-group">
<label>Company Name</label>
<input type="text" className="form-control" placeholder="Add Company Name" name="jobCompanyName" onChange={handleJobExperienceChange} />
</div>
<div className="form-row">
<div className="col">
<div className="form-group">
<label>Start Date</label>
<Datetime dateFormat="YYYY" timeFormat={false} onChange={(date) => setstartDate(date.year())} value={jobExperience.jobDateRangeStart} />
</div>
</div>
<div className="col">
<div className="form-group">
<label>End Date</label>
<Datetime dateFormat="YYYY" name="jobDateRangeEnd" timeFormat={false} onChange={(date) => setendDate(date.year())} value={jobExperience.jobDateRangeEnd} />
</div>
</div>
</div>
<div className="pt-1">
<div className="form-group">
<label>Job Role/Responsibilities</label>
<textarea style={{width: '100%'}} name="jobDescription" onChange={handleJobExperienceChange} />
<button type="submit" onClick={handleJobExperienceAdd} className="btn btn-success btn-sm btn-block">Add Job Experience</button>
</div>
</div>
</div>
</form>
</Col>
</Row>
</Container>
)
}
function JobExperience({jobExperience, index, refUpvote, refDownvote}) {
return (
<div>
<Card style={{width: '18rem'}} className="remove-border-radius">
<Card.Body>
<Card.Title><span><i className="fa fa-building"></i> {jobExperience.jobCompanyName}</span></Card.Title>
</Card.Body>
<Card.Text>
<i className="fa fa-calendar"></i> {jobExperience.jobDateRangeStart}-{jobExperience.jobDateRangeEnd}
</Card.Text>
<Card.Text>
<span><i className="fa fa-info-circle"></i> {jobExperience.jobDescription}</span>
</Card.Text>
<Button variant="primary" onClick={() => refUpvote(index)} className="remove-border-radius"><i className="fa fa-plus"></i> Reference {jobExperience.reference_upvote_count}</Button>
<Button variant="danger" onClick={() => refDownvote(index)} className="remove-border-radius"><i className="fa fa-minus-circle"></i> Reference {jobExperience.reference_downvote_count}</Button>
</Card>
</div>
)
}
Change the way you set your state from this:
const refUpvoteCount = (index) => {
const newReferences = [...jobExperience];
newReferences[index].reference_upvote_count++;
setjobExperience(newReferences);
};
const refDownvoteCount = (index) => {
const newReferences = [...jobExperience];
newReferences[index].reference_downvote_count++;
setjobExperience(newReferences);
};
To this:
const refUpvoteCount = (index) => {
setjobExperience((previousState) => {
const newReferences = [...previousState];
newReferences[index].reference_upvote_count++;
return newReferences;
});
}
const refDownvoteCount = (index) => {
setjobExperience((previousState) => {
const newReferences = [...previousState];
newReferences[index].reference_downvote_count++;
return newReferences;
});
}
You may also take note the difference to understand this other way of setting-up state that needs to have the the value of the previous state
Do it like this.
const myFunction = () => {
setState((previousState)=> newState)
}
If you need to get the reference of the previous state pass a callback function on setState and that call back function can take 1 parameter which that represent the previous state. And on the callback function you can do some operations if you need to. The return value of callback function will be the new state
And not like this
const myFunction = () => {
const newState = state
setState(newState)
}
This last code sample reference the previous state the wrong way and will not work
const [form, setForm] = useState({}); // form is the previous jobExperience object
const onChange = (event) => {
const { name, value } = event.target;
let savedValue = value;
/*
condition your changes below, you can also extract
the content of the condition to separate functions
*/
if (name === 'jobDateRangeStart') {
savedValue = []; // whatever you need to do with the value
}
if (name === 'jobDateRangeEnd') {
savedValue = []; // whatever you need to do with the value
}
if (name === 'jobDateRangeEnd') {
savedValue = []; // whatever you need to do with the value
}
setForm({ ...form, [name]: savedValue });
};
return (
<div className="pl-5 pr-5 pb-2">
<div className="form-group">
<label>Company Name</label>
<input
className="form-control"
name="jobCompanyName"
onChange={handleChange}
placeholder="Add Company Name"
type="text"
value={form.jobCompanyName || ''}
/>
</div>
<div className="form-row">
<div className="col">
<div className="form-group">
<label>Start Date</label>
<Datetime
dateFormat="YYYY"
onChange={handleChange}
timeFormat={false}
value={form.jobDateRangeStart || ''}
/>
</div>
</div>
<div className="col">
<div className="form-group">
<label>End Date</label>
<Datetime
dateFormat="YYYY"
name="jobDateRangeEnd"
onChange={handleChange}
timeFormat={false}
value={form.jobDateRangeEnd || ''}
/>
</div>
</div>
</div>
<div className="pt-1">
<div className="form-group">
<label>Job Role/Responsibilities</label>
<textarea
name="jobDescription"
onChange={handleChange}
value={form.jobDescription || ''}
style={{width: '100%'}}
/>
<button
className="btn btn-success btn-sm btn-block"
onClick={handleChange}
type="submit"
>
Add Job Experience
</button>
</div>
</div>
</div>
);
As far as i understood you are trying to add an object into an array with multiple fields . and the value of object will come from the values of your form . Here's how can you do it.
# Step 1 :
first create a state that will hold the array of objects .
const [arrayOfObjects , setArrayOfObjects ] = useState([]) ; // empty array initially
# Step 2 :
grab the value from your form's submit function and create the object
onSubmitHandler = () => {
const newObject = {
property1 : "some value " // this values will come from your form
property2 : "some value " // depending on your implementation you may have to maintain separate state for each property
}
const newState = [ ...arrayOfObjects , newObject ];
setArrayOfObjects(newState);
}

How to design State for Multiple objects using react-redux?

I need to create multiple medicine objects here. I just want to change state into array of objects. How to do that effectively? Also, want to implement controlled component for multiple medicine objects form.
Here's my component for a single medicine object:
export class MedicineForm extends Component {
state = {
medicine_name: "",
details: ""
}
static propTypes = {
postMedicine: PropTypes.func.isRequired
}
onChange = e => {
this.setState({
[e.target.name]: e.target.value
})
}
onSubmit = e => {
e.preventDefault()
const { medicine_name, details } = this.state
const medicine = { medicine_name, details }
this.props.postMedicine(medicine)
// Following code works as desired. Need to change state in this JSON Array of objects.
// this.props.postMedicine([
// {
// "id": 14,
// "medicine_name": "many5",
// "details": "sdknas"
// },
// {
// "id": 15,
// "medicine_name": "many6",
// "details": "sdknas"
// }
// ])
}
render() {
const { medicine_name, details } = this.state
return (
<Fragment>
<h1>Add Medicine</h1>
<form className="card card-body" onSubmit={this.onSubmit}>
<div className="form-row">
<div className="form-group col-md-3">
<label htmlFor="medicine_name">Medicine Name</label>
<input type="text" className="form-control" name="medicine_name" id="medicine_name" placeholder="Medicine Name" value={medicine_name} onChange={this.onChange} />
</div>
<div className="form-group col-md-3">
<label htmlFor="details">Details</label>
<input type="text" className="form-control" name="details" id="details" placeholder="Details" value={details} onChange={this.onChange} />
</div>
<div className="form-group mx-auto mt-3">
<button type="submit" className="btn btn-primary btn-lg">
Submit
</button>
</div>
</div>
</form>
</Fragment>
)
}
}
In actions, I have added following postMedicine method:
export const postMedicine = (medicine) => dispatch => {
axios.post('./api/medicine/', medicine)
.then(res => {
dispatch({
type: POST_MEDICINE,
payload: res.data
})
})
.catch(err => console.log(err))
}
//this is one row, add multiple rows as needed
state = {
medicines: [{medicine_name: "",
details: ""
}]
}
//other code
onChange = (e, i) => {
const newMedicines = this.state.medicines;
newMedicines[i] = {[e.target.name]: e.target.value, ...newMedicines[i]}
this.setState({medicines: newMedicines})
}
onSubmit = e => {
e.preventDefault()
const { medicine_name, details } = this.state
const medicine = { medicine_name, details }
this.props.postMedicine(medicine)
// Following code works as desired. Need to change state in this JSON Array of objects.
// this.props.postMedicine(this.state.medicines)
}
<form className="card card-body" onSubmit={this.onSubmit}>
{this.state.medicines.map((m, i) => (<div className="form-row">
<div className="form-group col-md-3">
<label htmlFor="medicine_name">Medicine Name</label>
<input type="text" className="form-control" name="medicine_name" id="medicine_name" placeholder="Medicine Name" value={m.medicine_name} onChange={(e) => this.onChange(e, i)} />
</div>
<div className="form-group col-md-3">
<label htmlFor="details">Details</label>
<input type="text" className="form-control" name="details" id="details" placeholder="Details" value={m.details} onChange={(e) => this.onChange(e, i)} />
</div>
<div className="form-group mx-auto mt-3">
<button type="submit" className="btn btn-primary btn-lg">
Submit
</button>
</div>
</div>))}
</form>
Form component has two parameter (aka props).
first one is item, wich determines how many form do you need.
1 form means you have group of two inputs [medicine_name,details]
2 = 4 input (2 group)
...etc
and second props is function named formHandler.
wich lifting data from child
export class MedicineForm extends Component {
state = {
medicine: [],
};
static propTypes = {
postMedicine: PropTypes.func.isRequired,
};
formHandler = (value) => {
this.setState({ medicine: value });
};
onSubmit = (e) => {
e.preventDefault();
this.props.postMedicine(this.medicine);
};
render() {
return (
<>
<h1>Add Medicine</h1>
{JSON.stringify(this.state.medicine)}
<form className="card card-body" onSubmit={this.onSubmit}>
<Form item="4" formHandler={this.formHandler} />
<div className="form-group mx-auto mt-3">
<button type="submit" className="btn btn-primary btn-lg">
Submit
</button>
</div>
</form>
</>
);
}
}
Form Component
class Form extends Component {
constructor(props) {
super(props);
}
state = {
medicine: [...Array(+this.props.item)].map((_, idx) => ({
id: idx + 1,
medicine_name: "",
details: "",
})),
};
static propTypes = {
item: PropTypes.string,
formHandler: PropTypes.func,
};
onChange = ({ target: { id, name, value } }) => {
this.setState((prevState) => {
const medicine = prevState.medicine.map((item) =>
item.id === Number(id) ? { ...item, [name]: value } : item
);
this.props.formHandler(
medicine.filter((item) => item["medicine_name"] || item["details"])
);
return {
medicine,
};
});
};
render() {
return (
<div className="form-row">
{this.state.medicine.map((item, id) => (
<div key={item.id}>
<div className="form-group col-md-3">
<label htmlFor="medicine_name">Medicine Name</label>
<input
type="text"
className="form-control"
name="medicine_name"
id={item.id}
value={item.medicine_name}
placeholder="Medicine Name"
onChange={this.onChange}
/>
</div>
<div className="form-group col-md-3">
<label htmlFor="details">Details</label>
<input
type="text"
className="form-control"
name="details"
id={item.id}
value={item.details}
placeholder="Details"
onChange={this.onChange}
/>
</div>
</div>
))}
</div>
);
}
}
there is check if object has some value then lifting data.
you can change logic optional
medicine.filter((item) => item["medicine_name"] || item["details"])
You could do something like this in redux store:
[
{ id: 1, medicineName: '', details: '' },
{ id: 2, medicineName: '', details: '' },
...
]
And to make your input fields controlled just handle the state in the component.

Getting the value of list of inputs in react

I have list of input tags in my react app. I want to get the value of all inputs when I click on submit button.
I can get the value of one input, but not able to get all the values in one go.
keys.map(i => <Input fullWidth defaultValue={i} />)
<Button>Submit</Button>
get the list of values
Sample application for multiple inputs
const App = () => {
const [people, setPeople] = React.useState([
{ firstName: "Herry", lastName: "Sejal" },
{ firstName: "John", lastName: "Siri" },
{ firstName: "Bukky", lastName: "Sera" }
]);
const [person, setPerson] = React.useState({ firstName: "", lastName: "" });
const onChange = e => {
setPerson({ ...person, [e.target.name]: e.target.value });
};
const onSubmit = e => {
e.preventDefault();
const newVal = [...people, person];
setPeople(newVal);
setPerson({ firstName: "", lastName: "" });
};
return (
<div className="container">
<div className="row">
<div className="col">
<h2>Add a person: </h2>
<hr />
<form onSubmit={onSubmit}>
<div className="form-group">
<input
type="text"
className="form-control"
name="firstName"
placeholder="First Name.."
value={person.firstName}
onChange={onChange}
/>
</div>
<div className="form-group">
<input
type="text"
className="form-control"
name="lastName"
placeholder="Last Name.."
value={person.lastName}
onChange={onChange}
/>
</div>
<button className="btn btn-success" type="submit">
Add person
</button>
</form>
</div>
<div className="col">
<h2>People: </h2>
<hr />
{people.map(p => (
<div key={Math.random() * 1000000000}>
<p>
{p.firstName} {p.lastName}
</p>
</div>
))}
</div>
</div>
</div>
);
};

Resources