React应用中输入框打字时失去焦点的问题求助
React应用中输入框打字时失去焦点的问题求助
嘿,我完全懂你现在的困扰——输入框刚打一个字就失去焦点,根本没法正常输入!你猜的方向是对的,确实是组件重新渲染导致的问题,我来帮你捋清楚怎么解决。
问题根源
你把InputForm和RecipeList这两个子组件直接定义在RecipeApp组件的内部了。React每次渲染RecipeApp的时候(比如你在输入框打字改变recipeInput状态时),都会重新创建这两个子组件的定义。这就意味着,原来的输入框DOM元素会被销毁,然后重新生成一个全新的输入框,自然就失去焦点了。
修复方案
把InputForm和RecipeList移到RecipeApp组件的外部,这样它们就不会随着RecipeApp的重新渲染而被反复创建。另外我还注意到你的代码里,除了recipeInput的输入框,其他几个输入框都没绑定onChange事件,根本没法输入内容,我也一起帮你补上了。
下面是修复后的完整代码:
import { useState } from 'react'; // 把InputForm移到RecipeApp外部 function InputForm({ recipeInput, setRecipeInput, summaryInput, setSummaryInput, ingredientsInput, setIngredientsInput, cookTimeInput, setCookTimeInput, handleAddRecipe }) { 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" onChange={(e) => setSummaryInput(e.target.value)} /> <p>Ingredients</p> <input value={ingredientsInput} placeholder="List up to four ingredients, seperated by a comma" onChange={(e) => setIngredientsInput(e.target.value)} /> <p>Cook Time (minutes)</p> <input value={cookTimeInput} placeholder="Time in minutes" onChange={(e) => setCookTimeInput(e.target.value)} /> <button>Add</button> </form> ); } // 把RecipeList移到RecipeApp外部 function RecipeList({ recipes }) { return ( <ul> {recipes.map((recipe) => ( <li key={recipe.id}> {recipe.title} <button>View</button> <button>Delete</button> </li> ))} </ul> ); } 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(""); } return ( <div className="RecipeApp"> <InputForm recipeInput={recipeInput} setRecipeInput={setRecipeInput} summaryInput={summaryInput} setSummaryInput={setSummaryInput} ingredientsInput={ingredientsInput} setIngredientsInput={setIngredientsInput} cookTimeInput={cookTimeInput} setCookTimeInput={setCookTimeInput} handleAddRecipe={handleAddRecipe} /> <h2>List of recipes:</h2> <RecipeList recipes={recipes} /> </div> ); }
关键修改点
- 组件移到外部:把
InputForm和RecipeList从RecipeApp内部移到外部,通过props传递需要的状态和方法,这样它们就不会被反复创建。 - 补上缺失的onChange:给summary、ingredients、cookTime的输入框都绑定了
onChange事件,现在这些输入框终于可以正常输入了。 - props传递状态:子组件通过props获取父组件的状态和回调函数,保持数据流向的清晰。
这样修改之后,你在输入框打字的时候,输入框就不会再失去焦点了,其他几个输入框也能正常输入内容了!
备注:内容来源于stack exchange,提问作者Declan Davies




