'Creating an array of objects from react events
I am trying to create a new object for ingredient quantity measure for each new ingredient the user creates. I can make the object for 1 of the ingredient-triad divs but I am stumped about how to create several objects with different ingredients added by user eg.
ingredientList = [
{
ingredient_name: flour,
ingredient_quantity: 1,
ingredient_measure: cup
},
{
ingredient_name: water,
ingredient_quantity: 1,
ingredient_measure: tbsp
}
]
etc.
Here is where I have gotten to:
export default function Recipe() {
const [name, setName] = useState('')
const [method, setMethod] = useState('')
const [ingredient, setIngredient] = useState('')
const [ingredientyQty, setIngredientQty] = useState('')
const [ingredientMeasure, setIngredientMeasure] = useState('')
const ingredientList = []
const recipeIngredient = {
ingredient_name: ingredient,
quantity: ingredientyQty,
measure: ingredientMeasure,
}
ingredientList.push(recipeIngredient)
const sendRecipeName = function (e) {
e.preventDefault()
fetch('http://localhost:3001/recipe', {
method: 'POST',
headers: { 'Content-type': 'application/json' },
body: JSON.stringify({ name: name, method: method }),
})
.then((resp) => resp.json())
.then((json) => console.log(json))
}
return (
<div>
[...]
<div className="ingredient-triad">
<input
className="ingredient"
type="text"
onChange={(e) => setIngredient(e.target.value)}
></input>
<input
className="quantity"
type="text"
onChange={(e) => setIngredientQty(e.target.value)}
></input>
<select
className="dropdown"
name="measure"
id="measure"
onChange={(e) => setIngredientMeasure(e.target.value)}
>
<option value="cup">cup</option>
[...]
</select>
</div>
<div className="ingredient-triad">
<input
className="ingredient"
type="text"
onChange={(e) => setIngredient(e.target.value)}
></input>
<input
className="quantity"
type="text"
onChange={(e) => setIngredientQty(e.target.value)}
></input>
<select
className="dropdown"
name="measure"
id="measure"
onChange={(e) => setIngredientMeasure(e.target.value)}
>
<option value="cup">cup</option>
[...]
</select>
</div>
<div className="save-button-container">
<button className="save-recipe" onClick={(e) => sendRecipeName(e)}>
Submit Recipe
</button>
</div>
</form>
</div>
</div>
)
}
Solution 1:[1]
import React, { useState } from "react";
const init = {
ingredient_name: "",
quantity: "",
measure: ""
};
export default function App() {
const [ingredientList, setIngredientList] = useState([
{
ingredient_name: "",
quantity: "",
measure: ""
}
]);
const handleChange = (e, i) => {
const { name, value } = e.target;
setIngredientList((prevState) => {
const newIngredientList = [...prevState];
newIngredientList[i][name] = value;
return [...newIngredientList];
});
};
return (
<>
[...]
{ingredientList.map((list, i) => (
<div key={i} className="ingredient-triad">
<input
className="ingredient"
name="ingredient_name"
type="text"
value={list.ingredient_name}
onChange={(e) => handleChange(e, i)}
></input>
<input
className="quantity"
name="quantity"
type="text"
value={list.quantity}
onChange={(e) => handleChange(e, i)}
></input>
<select
className="dropdown"
name="measure"
id="measure"
value={list.measure}
onChange={(e) => handleChange(e, i)}
>
<option value="" disabled>
--none--
</option>
<option value="cup">cup</option>
</select>
<button onClick={() => setIngredientList((prev) => [...prev, init])}>
+
</button>
</div>
))}
[...]
</>
);
}
I think this is what you are looking for :)
Solution 2:[2]
Try this below code:
export default function Recipe() {
const [name, setName] = useState('')
const [method, setMethod] = useState('')
const [ingredientList, setIngredientList] = useState([])
const [ingredient, setIngredient] = useState('')
const [ingredientyQty, setIngredientQty] = useState('')
const [ingredientMeasure, setIngredientMeasure] = useState('')
console.log(ingredientList)
const sendRecipeName = function (e) {
e.preventDefault()
const recipeIngredient = {
ingredient_name: ingredient,
quantity: ingredientyQty,
measure: ingredientMeasure,
}
setIngredientList((prev) => [...prev, recipeIngredient])
fetch('http://localhost:3001/recipe', {
method: 'POST',
headers: { 'Content-type': 'application/json' },
body: JSON.stringify({ name: name, method: method }),
})
.then((resp) => resp.json())
.then((json) => console.log(json))
}
return (
<div>
[...]
<div className="ingredient-triad">
<input
className="ingredient"
type="text"
onChange={(e) => setIngredient(e.target.value)}
></input>
<input
className="quantity"
type="text"
onChange={(e) => setIngredientQty(e.target.value)}
></input>
<select
className="dropdown"
name="measure"
id="measure"
onChange={(e) => setIngredientMeasure(e.target.value)}
>
<option value="cup">cup</option>
[...]
</select>
</div>
<div className="ingredient-triad">
<input
className="ingredient"
type="text"
onChange={(e) => setIngredient(e.target.value)}
></input>
<input
className="quantity"
type="text"
onChange={(e) => setIngredientQty(e.target.value)}
></input>
<select
className="dropdown"
name="measure"
id="measure"
onChange={(e) => setIngredientMeasure(e.target.value)}
>
<option value="cup">cup</option>
[...]
</select>
</div>
<div className="save-button-container">
<button className="save-recipe" onClick={(e) => sendRecipeName(e)}>
Submit Recipe
</button>
</div>
</form>
</div>
</div>
)
}
Solution 3:[3]
First, I think you are missing the company field from your UpdateProductUserForm.
Add that in there:
class UpdateProductUserForm(AddUsersForm):
first_nm = StringField('First Name*', validators=[DataRequired()])
last_nm = StringField('Last Name*', validators=[DataRequired()])
company = SelectField('Company*', validators=[DataRequired()], choices=[])
disable = SubmitField('Deactivate')
Notice that we define it as an empty list. Then we update it however we want in the view:
@approvals.route('/productapproval/addproductUser/<int:prod_user_key>', methods=['GET', 'POST'])
def edit_product_users(prod_user_key):
productUser = ProductUsers.query.get_or_404(prod_user_key)
# get all the companies
companies = [comp.prod_id for comp in Company.query.filter(Company.member_status!=500).all()]
# move current company item to start of list
current_company_index = companies.index(productUser.prod_id)
companies.insert(0, companies.pop(current_company_index))
form = UpdateProductUserForm()
form.company.choices = companies
form.first_nm.data = productUser.first_nm
form.last_nm.data = productUser.last_nm
if form.validate_on_submit():
productUser.org_id = form.company.data
productUser.first_nm = form.first_nm.data
productUser.last_nm = form.last_nm.data
db.session.add(productUser)
db.session.commit()
flash('User Account Updated', 'success')
return redirect(url_for('approvals.users', prod_user_key=prod_user_key))
return render_template('/productapproval/addusers.html', form=form)
I noticed you were fetching the user twice. You don't need to do that. Also you weren't properly adding the updated user to the database session. I've fixed those things in the above code.
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 | omnicron96 |
| Solution 2 | VMT |
| Solution 3 |
