ReactJS状态更新后输入框值未同步问题求助
问题:作物种植面积输入框值无法同步状态更新
我正在实现一个作物列表功能,用户可修改每种作物的种植面积(surface)、产量(yield)和价格(price)。初始状态下所有作物的面积为0,产量和价格已预设,初始状态如下:
C1 : ['Blé tendre', 0, 8.3, 191] C2 : ["Orge d'hivers et escourgeon", 0, 6.75, 181] C3 : ['Maïs grain', 0, 9.99, 178] C4 : ['Soja', 0, 2.73, 379]
当用户在"Blé tendre"的面积输入框中输入20时,console.log显示状态已更新:
C1 : ['Blé tendre', 20, 8.3, 191] C2 : ["Orge d'hivers et escourgeon", 0, 6.75, 181] C3 : ['Maïs grain', 0, 9.99, 178] C4 : ['Soja', 0, 2.73, 379]
但输入框的值并未同步变化。
主文件 Assolement.js
import React, { useState} from 'react'; import {Navigate} from 'react-router-dom' import Entete from '../MEP/entete' import Culture from './culture_assol' function Assolement() { const [goToExploit, setGoToExploit] = useState(false) const [data, setData] = useState({"C1": ["Blé tendre", 0,8.3, 191], "C2": ["Orge d'hivers et escourgeon",0, 6.75, 181], "C3" :["Maïs grain",0, 9.99, 178], "C4": ["Soja",0, 2.73, 379]}) const table_assol= Object.keys(data).map(key => ( <Culture keys={key} data={data} MAJ_surf={MAJ_surf} libelle={data[key][0]} /> )) function MAJ_surf(key,surf) { var newData= data; newData[key][1] = parseFloat(surf)//execute the manipulations setData(newData) setData(prev => { return prev; }) console.log('surf') console.log(surf) console.log('data') console.log(data) console.log(data[key][1]) } function handleSubmit(event) { event.preventDefault() setGoToExploit(true) } if(goToExploit) { return <Navigate push to={`/exploitation`}/> } return ( <div> <Entete titre="Assolement"/> <div className='container'> <h1> </h1> <form onSubmit={handleSubmit}> <div className='table_assol'> {table_assol} </div> <div className='row'> <button type='submit' className='validation'> Enregistrer </button> </div> </form> </div> </div> ); } export default Assolement;
子组件 culture_assol.js
import React from 'react' const Culture = ({keys,data, MAJ_surf, libelle}) => { function handleChangeSurface(event) { var surf = event.target.value; MAJ_surf(keys, surf); console.log(data) console.log(data[keys]) console.log(data[keys][1]) } return ( <div className='row ligne_assol'> <div className='col_assol col_libelle'> {libelle} </div> <div className='col_assol col_surface'> <div className='videBlocAssol'> <input className='input_assol' onChange={handleChangeSurface} value= {data[keys][1]} placeholder='0' type='text'/> <div className='pleinBlocAssol'> ha </div> </div> </div> <div className='col_assol col_rdt'> <div className='videBlocAssol'> <input className='input_assol' value= {data[keys][2]} type='text'/> <div className='pleinBlocAssol'> t/ha </div> </div> </div> <div className='col_assol col_prix'> <div className='videBlocAssol'> <input className='input_assol' value= {data[keys][3]} type='text'/> <div className='pleinBlocAssol'> €/t </div> </div> </div> <div className='col_assol col_PB_unitaire'> {Math.round(data[keys][2]*data[keys][3])} € </div> <div className='col_assol col_PB_tit_Prod'> {Math.round(data[keys][1]*data[keys][2]*data[keys][3])} € </div> </div> ) } export default Culture;
已尝试的方法
- 将
MAJ_surf函数移至culture_assol组件内 - 移除重复的
setData调用,仅保留setData(newData)
解决方案
问题核心是直接修改原状态对象,未创建新引用,React依赖状态引用变化触发重新渲染。
1. 修复状态更新逻辑
修改MAJ_surf函数,创建状态的深拷贝后再修改,确保生成新的引用:
function MAJ_surf(key, surf) { setData(prevData => { // 拷贝外层对象 const newData = {...prevData}; // 拷贝对应作物的数组,修改面积值 newData[key] = [...prevData[key]]; newData[key][1] = parseFloat(surf); return newData; }); }
这种方式比JSON.parse(JSON.stringify(data))更高效,且能兼容JSON无法序列化的类型。
2. 优化组件key传递
React列表渲染需要指定key属性,修正table_assol的map逻辑:
const table_assol= Object.keys(data).map(key => ( <Culture key={key} // React要求的列表项key属性 keys={key} // 自定义参数,用于访问data data={data} MAJ_surf={MAJ_surf} libelle={data[key][0]} /> ))
失效原因说明
之前的代码中var newData = data只是复制了原状态的引用,修改newData[key][1]本质是直接修改原状态对象。React对比前后状态时发现引用未变,不会触发组件重新渲染,因此输入框值无法更新。即使调用setData(prev => prev),由于引用未变,依然不会触发渲染。
内容的提问来源于stack exchange,提问作者Aliénor
相关产品推荐
相关产品推荐

