React父组件通过ref传值时子组件useState不更新问题
问题根源
- Ant Design 表单的
initialValue属性仅在表单首次渲染时生效,后续你修改子组件内部的objCounter状态,表单字段不会自动同步最新值,这是值不更新的核心原因。 - React 状态更新是异步批量执行的,父组件
clickMe方法中调用setCounter后立刻读取counter拿到的是更新前的旧值,你当前直接传counter*2的计算值暂时没问题,但后续调整逻辑很容易触发闭包陷阱。 useImperativeHandle未声明依赖数组,不符合React Hooks规范,存在闭包拿到旧值的潜在风险。
修复方案
父组件修改(优化异步状态调用逻辑)
把调用子组件showDrawer的逻辑放到useEffect里,等counter状态更新完成后再触发,避免闭包问题:
export default function Form1() { const [count, setCount] = useState(0); const [counter, setCounter] = useState(10); const AddNewRef = useRef(); // 监听counter变化,更新完成后再调用子组件方法 useEffect(() => { AddNewRef.current?.showDrawer(counter); }, [counter]) const clickMe=() => { setCount(prev => prev + 1); setCounter(prev => prev * 2); // 函数式更新避免闭包问题 } return ( <div> <p>You clicked count: {count} & counter: {counter} times</p> { count > 10 ? ( <p className='red'>your count is greater then 10</p> ) : ( <p className='green'>your count is less then 10</p> ) } <button onClick={clickMe}> Click me </button> <AddNew ref={AddNewRef} Count={count} Counter={counter} /> </div> ) }
子组件修改(修复表单值不更新问题)
不要依赖initialValue同步动态值,调用Form实例的setFieldsValue方法手动更新表单字段:
import { Form } from 'antd'; const AddNew=forwardRef((props, ref) => { const [form] = Form.useForm(); // 获取表单实例 const[objCounter, setobjCounter] = useState(null); useImperativeHandle( ref, () => ({ showDrawer(count) { setobjCounter(count); // 手动更新指定表单字段的值 form.setFieldsValue({ packageName: count }) } }), [form] // 补全依赖数组 ) // 原有visible、onClose、onFinish等逻辑保持不变 return ( <> <Drawer title={<span> <i className='fa-solid fa-kaaba' /> Haj Setup Form</span>} width={window.innerWidth > 900 ? 800 : window.innerWidth - 50} onClose={onClose} visible={visible} bodyStyle={{ paddingBottom: 80 }} extra={ <Space> <Button onClick={onClose}>Cancel</Button> <Button onClick={onClose} type="primary"> Submit </Button> </Space> } > <Form style={{display: formVisible ? 'block' : 'none'}} form={form} // 绑定表单实例 layout="vertical" onFinish={onFinish} onFinishFailed={onFinishFailed} autoComplete="off" hideRequiredMark > <Row gutter={16}> <Col xs={24} sm={24} md={24} lg={24}> <Form.Item name="packageName" label="Package Name" rules={[{ required: true, message: 'Please enter package name' }]} initialValue={objCounter} > <Input style={{width: '100%'}} maxLength={100} /> </Form.Item> </Col> </Row> </Form> </Drawer> </> ) }); export default AddNew
内容的提问来源于stack exchange,提问作者Muhammad Faheem Chughtai
相关产品推荐
相关产品推荐

