You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React组件中handleItemNameChange等事件函数未定义问题求助

问题根源

你代码里的核心问题是直接通过innerHTML操作DOM来替换表单内容,这完全违背了React的声明式渲染逻辑:

  • 当你用innerHTML插入onChange={handleItemNameChange}这类代码时,浏览器只会把它当成纯文本/字符串解析,不会识别为React的事件绑定,自然找不到对应的函数。
  • 直接操作DOM会脱离React的状态管理,导致组件状态和实际DOM不同步,后续的状态更新也无法正确触发重渲染。

另外,你在return的JSX里错误地使用了模板字符串语法${itemName},React的JSX中应该用大括号包裹变量,即{itemName}。

修复方案

完全移除innerHTML的DOM操作,改用React的状态(ingDone)来控制不同阶段的表单显示,让React负责DOM的渲染和事件绑定:

修正后的完整代码:

import React, { useState } from "react";
import "../../css/AddMenuItem.css"

function MenuAdder() {
  const [ingredient, setIngredient] = useState("");
  const [quantity, setQuantity] = useState("");
  const [itemName, setItemName] = useState("");
  const [price, setPrice] = useState("");
  const [ingredients, setIngredients] = useState([]);
  const [ingDone, setIngDone] = useState(false);

  const handleAddIngredient = () => {
    const newIngredient = { name: ingredient, quantity: quantity };
    setIngredients([...ingredients, newIngredient]);
    setIngredient("");
    setQuantity("");
  };

  const handleItemNameChange = (event) => {
    setItemName(event.target.value);
  };

  const handlePriceChange = (event) => {
    setPrice(event.target.value);
  };

  const handleDoneIngredients = () => {
    console.log(ingredients);
    fetch("http://localhost:3001/addMenu", {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ ingredients })
    })
    .then(response => response.json())
    .then(data => {
      console.log(data);
      if (data.message === "fault") {
        console.log("fault");
      }
      // 只需要更新状态,让React自动渲染对应的表单
      setIngDone(true);
    })
    .catch(error => {
      console.error(error);
      console.log("paad");
      // 错误时重置状态,回到初始表单
      setIngDone(false);
    });
  };

  const handleAddOrder = () => {
    fetch("http://localhost:3001/addmenu/completeMenu", {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ name: itemName, price: price })
    })
    .then(response => response.json())
    .then(data => { console.log(data); })
    .catch(error => { console.error(error); });
    // 重置状态,回到添加食材的阶段
    setIngDone(false);
    setItemName("");
    setPrice("");
    setIngredients([]);
  };

  const handleIngredientChange = (event) => {
    setIngredient(event.target.value);
  };

  const handleQuantityChange = (event) => {
    setQuantity(event.target.value);
  };

  return (
    <div id="menuadder">
      {/* 根据ingDone状态切换标题 */}
      <h3>{ingDone ? "Add Menu Item" : "Add Ingredients"}</h3>
      <form id="menuadder-form">
        {/* 食材添加阶段 */}
        {!ingDone && (
          <>
            <label htmlFor="ingredient">Ingredient:</label>
            <input 
              type="text" 
              id="ingredient" 
              name="ingredient" 
              value={ingredient} 
              onChange={handleIngredientChange} 
              required 
            />
            <label htmlFor="quantity">Quantity:</label>
            <input 
              type="number" 
              id="quantity" 
              name="quantity" 
              value={quantity} 
              onChange={handleQuantityChange} 
              required 
            />
            <button type="button" onClick={handleAddIngredient}>Add Ingredient</button>
            
            {ingredients.length > 0 && (
              <div>
                <h3>Added Ingredients:</h3>
                <ul>
                  {ingredients.map((ingredient, index) => (
                    <li key={index}>{ingredient.name} - {ingredient.quantity}</li>
                  ))}
                </ul>
                <button type="button" onClick={handleDoneIngredients}>Done with Ingredients</button>
              </div>
            )}
          </>
        )}

        {/* 菜品信息填写阶段 */}
        {ingDone && (
          <>
            <label htmlFor="item-name">Item Name:</label>
            <input 
              type="text" 
              id="item-name" 
              name="item-name" 
              value={itemName} 
              onChange={handleItemNameChange} 
              required 
            />
            <label htmlFor="price">Price:</label>
            <input 
              type="number" 
              id="price" 
              name="price" 
              value={price} 
              onChange={handlePriceChange} 
              required 
            />
            <button type="button" onClick={handleAddOrder}>Add Order</button>
          </>
        )}
      </form>
    </div>
  );
}

export default MenuAdder;

关键修改点

  1. 移除所有innerHTML操作,改用ingDone状态的条件渲染来切换两个阶段的表单内容,让React全程管理DOM和事件绑定。
  2. 修正return中JSX的变量语法,把${itemName}改成{itemName}。
  3. 在handleAddOrder中重置相关状态,让组件回到初始的食材添加状态。
  4. 调整了条件渲染的结构,用<>(Fragment)包裹多个元素,符合JSX语法要求。

这样修改后,React会正确识别所有事件处理函数,状态更新也能自动触发DOM重渲染,完全解决函数无法被检测到的问题。

内容的提问来源于stack exchange,提问作者Ahnaf Hossain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 07:45:03