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
相关产品推荐
相关产品推荐

