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

React中如何通过onChange绑定number类型input的value值

问题根因

你现在无法获取页数字段输入值、输入后状态不更新,核心是3个问题:

  • 页数pages、语言数languages两个输入框完全没绑定状态更新事件,也没有绑定对应state值,属于非受控组件,用户输入的内容根本不会同步到cost状态里
  • 现有的handleOnChange方法是专门给复选框写的,逻辑是直接对字段值做布尔取反(!newCost[name]),完全不适用文本/数字类型的输入框
  • 代码里存在冗余状态、属性书写错误的问题,会进一步导致状态取值不同步

修复方案

1. 补全React Hook导入

你的代码里使用了useState、useEffect但没有从react包中导入,首先补上导入语句:

import { useState, useEffect } from "react";
import "./App.css";

2. 改写通用onChange处理逻辑,兼容所有输入类型

不同类型输入框的取值逻辑不同:复选框取event.target.checked的布尔值,数字输入框要把输入内容转成数值类型,避免字符串拼接错误。把原有handleOnChange替换为以下代码:

const handleOnChange = (event) => {
  const { name, type, value, checked } = event.target;
  setCost(prev => ({
    ...prev,
    [name]: type === 'checkbox' ? checked : type === 'number' ? Number(value) : value
  }))
};

3. 给输入框绑定受控属性

给页数、语言数两个输入框补上value绑定对应state、onChange绑定更新方法,同时把根节点写错的classname改成React要求的驼峰写法className,复选框也补上checked属性保证受控:

return (
  <div className="App">
    <h3> Which services do you require?</h3>
    <p>
      <input
        type="checkbox"
        name="website"
        onChange={handleOnChange}
        checked={cost.website}
      />{" "}
      A website (500 €)
    </p>
    {/* 直接用cost.website判断即可,不需要单独维护isWebChecked状态 */}
    {cost.website && (
      <div className="modal">
        <label htmlFor="pages">Number of web pages </label>
        <input 
          type="number" 
          name="pages"
          value={cost.pages}
          onChange={handleOnChange}
          min={1}
        />
        <br />
        <br />
        <label htmlFor="lang">Number of languages </label>
        <input 
          type="number" 
          name="languages"
          value={cost.languages}
          onChange={handleOnChange}
          min={1}
        />
      </div>
    )}
    <p>
      <input
        type="checkbox"
        name="seo"
        onChange={handleOnChange}
        checked={cost.seo}
      />{" "}
      A SEO consultancy (300 €)
    </p>
    <p>
      <input
        type="checkbox"
        name="google"
        onChange={handleOnChange}
        checked={cost.google}
      />{" "}
      A Google Ads Campaign (200 €)
    </p>

    <p>
      {" "}
      <strong>Total price: {total} €</strong>{" "}
    </p>
  </div>
);

4. 简化总价计算逻辑,去掉冗余写法

原代码里setTotal((prev) => (prev = newTotal))、setCost((prev) => (prev = newCost))属于无效冗余写法,直接传入新值即可,去掉多余的isWebChecked状态,避免多份状态不同步:

useEffect(() => {
  const newTotal =
    0 +
    (cost.website ? 500 : 0) +
    (cost.seo ? 300 : 0) +
    (cost.google ? 200 : 0) +
    ((cost.pages > 1 || cost.languages > 1) ? cost.pages * cost.languages * 30 : 0);
  setTotal(newTotal);
}, [cost]);

修复后完整可运行代码
import { useState, useEffect } from "react";
import "./App.css";

function App(props) {
  const [total, setTotal] = useState(0);
  const [cost, setCost] = useState({
    website: false,
    seo: false,
    google: false,
    pages: 1,
    languages: 1,
  });

  useEffect(() => {
    const newTotal =
      0 +
      (cost.website ? 500 : 0) +
      (cost.seo ? 300 : 0) +
      (cost.google ? 200 : 0) +
      ((cost.pages > 1 || cost.languages > 1) ? cost.pages * cost.languages * 30 : 0);
    setTotal(newTotal);
  }, [cost]);

  const handleOnChange = (event) => {
    const { name, type, value, checked } = event.target;
    setCost(prev => ({
      ...prev,
      [name]: type === 'checkbox' ? checked : type === 'number' ? Number(value) : value
    }))
  };

  return (
    <div className="App">
      <h3> Which services do you require?</h3>
      <p>
        <input
          type="checkbox"
          name="website"
          onChange={handleOnChange}
          checked={cost.website}
        />{" "}
        A website (500 €)
      </p>
      {cost.website && (
        <div className="modal">
          <label htmlFor="pages">Number of web pages </label>
          <input 
            type="number" 
            name="pages"
            value={cost.pages}
            onChange={handleOnChange}
            min={1}
          />
          <br />
          <br />
          <label htmlFor="lang">Number of languages </label>
          <input 
            type="number" 
            name="languages"
            value={cost.languages}
            onChange={handleOnChange}
            min={1}
          />
        </div>
      )}
      <p>
        <input
          type="checkbox"
          name="seo"
          onChange={handleOnChange}
          checked={cost.seo}
        />{" "}
        A SEO consultancy (300 €)
      </p>
      <p>
        <input
          type="checkbox"
          name="google"
          onChange={handleOnChange}
          checked={cost.google}
        />{" "}
        A Google Ads Campaign (200 €)
      </p>

      <p>
        <strong>Total price: {total} €</strong>
      </p>
    </div>
  );
}

export default App;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 08:54:19