You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

React应用中输入框打字时失去焦点的问题求助

React应用中输入框打字时失去焦点的问题求助

嘿,我完全懂你现在的困扰——输入框刚打一个字就失去焦点,根本没法正常输入!你猜的方向是对的,确实是组件重新渲染导致的问题,我来帮你捋清楚怎么解决。

问题根源

你把InputFormRecipeList这两个子组件直接定义在RecipeApp组件的内部了。React每次渲染RecipeApp的时候(比如你在输入框打字改变recipeInput状态时),都会重新创建这两个子组件的定义。这就意味着,原来的输入框DOM元素会被销毁,然后重新生成一个全新的输入框,自然就失去焦点了。

修复方案

InputFormRecipeList移到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>
  );
}

关键修改点

  1. 组件移到外部:把InputFormRecipeListRecipeApp内部移到外部,通过props传递需要的状态和方法,这样它们就不会被反复创建。
  2. 补上缺失的onChange:给summary、ingredients、cookTime的输入框都绑定了onChange事件,现在这些输入框终于可以正常输入了。
  3. props传递状态:子组件通过props获取父组件的状态和回调函数,保持数据流向的清晰。

这样修改之后,你在输入框打字的时候,输入框就不会再失去焦点了,其他几个输入框也能正常输入内容了!

备注:内容来源于stack exchange,提问作者Declan Davies

火山引擎 最新活动