I am building a React application that uses an input field to allow users to type a recipe title, then, when they submit the form, the recipe should be added to a RecipeList.
At the moment, my code isn’t working correctly because I can only type 1 word before the input field loses focus. If I had to guess, I would guess that the form is re-rendering somehow when I type a letter.
I want to continue typing without my input losing focus.
Here is my code:
function RecipeApp() {
const [recipes, setRecipes] = useState(initialRecipes);
const [recipeInput, setRecipeInput] = useState("");
const [summaryInput, setSummaryInput] = useState("");
const [ingredientsInput, setIngredientsInput] = useState([]);
const [cookTimeInput, setCookTimeInput] = useState("");
function handleAddRecipe(e) {
e.preventDefault();
if (!recipeInput || !summaryInput || !ingredientsInput || !cookTimeInput) {
alert("Please fill out all fields!");
return;
}
const newRecipe = {
id: recipes.length,
title: recipeInput,
summary: summaryInput,
ingredients: ingredientsInput.split(",").reduce(
(acc, ing, idx) => ({
...acc,
[`ingredient${idx + 1}`]: ing.trim(),
}),
{}
),
cookTime: parseInt(cookTimeInput, 10),
};
setRecipes([...recipes, newRecipe]);
setRecipeInput("");
setSummaryInput("");
setIngredientsInput("");
setCookTimeInput("");
}
function InputForm() {
return (
<form onSubmit={handleAddRecipe}>
<p>Recipe name</p>
<input
value={recipeInput}
onChange={(e) => setRecipeInput(e.target.value)}
/>
<p>Summary</p>
<input value={summaryInput} placeholder="Enter a description" />
<p>Ingredients</p>
<input
value={ingredientsInput}
placeholder="List up to four ingredients, seperated by a comma"
/>
<p>Cook Time (minutes)</p>
<input value={cookTimeInput} placeholder="Time in minutes" />
<button>Add</button>
</form>
);
}
function RecipeList() {
return (
<ul>
{recipes.map((recipe) => (
<li key={recipe.id}>
{recipe.title}
<button>View</button>
<button>Delete</button>
</li>
))}
</ul>
);
}
return (
<div className="RecipeApp">
<InputForm />
<h2>List of recipes:</h2>
<RecipeList />
</div>
);
}