React中使用select组件更新state无延迟的实现方法
React Select切换时State更新延迟问题
切换select元素时,state的实际更新存在一个渲染周期的延迟,现有方案无效,useEffect仍显示上一渲染周期的旧状态,该如何解决?
父组件代码
import React, {useCallback, useEffect, useState} from 'react' import Dropdown from '../components/Dropdown.js' const ValueCalculation = () => { const industryData = require('../../../backend/standard_data/industry_benchmarks.json') var industryList = [] industryData.map((record)=>{ var x = record.Industry; industryList.push(x) }) const [industry, setIndustry] = useState(industryList[8]); const updateIndustry = (updatedValue)=>{ console.log(updatedValue); //<--这里能拿到正确的新值! setIndustry(updatedValue) //<--当前作用域里state没立刻更新 console.log(industry); //<--这里显示的还是旧值 } useEffect(()=>{ console.log(industry); //<--仍然显示上一渲染周期的旧值 },[]) return ( <div> <Dropdown label="Industry" value={industry} onChange={(e)=>updateIndustry(e.target.value)} list={industryList} /> </div> ) } export default ValueCalculation
子Dropdown组件代码
import React from 'react' const Dropdown = (props) => { return ( <div className="form-group mb-3"> <label>{props.label}</label> <select className="form-control" value={props.value} onChange={props.onChange} > { props.list.map(item=>( <option key={props.list.indexOf(item)} value={item}>{item}</option> )) } </select> </div> ) } export default Dropdown
解决方法
1. 先明确React State的异步特性
React里的setState(包括函数式组件的setIndustry)是异步操作,调用后不会立刻更新当前作用域内的state值。所以你在updateIndustry里直接console.log(industry)看到旧值是正常的——这个industry是当前函数闭包捕获的更新前的值。
2. 修正useEffect的依赖项
你当前的useEffect依赖数组是空的,只会在组件首次渲染时执行一次,自然不会监听industry的变化。要让它在industry更新时触发,把industry加入依赖数组:
useEffect(()=>{ console.log(industry); //现在会在state更新后打印最新值 },[industry])
3. 若需立即使用新值,直接用传入的参数
如果要在updateIndustry里立刻基于新值做逻辑,直接用updatedValue即可,不用等state更新:
const updateIndustry = (updatedValue)=>{ console.log(updatedValue); //直接使用这个新值 setIndustry(updatedValue); // 这里可以基于updatedValue执行后续操作,无需依赖state }
4. 优化Dropdown的key属性
当前Dropdown中用props.list.indexOf(item)作为key,若列表存在重复值会导致key冲突,建议用item本身(确保item唯一)作为key:
<option key={item} value={item}>{item}</option>
内容的提问来源于stack exchange,提问作者aghosh03
相关产品推荐
相关产品推荐

