如何在父组件点击按钮时获取动态渲染的MUI子组件值?
解决方法:通过状态提升实现父组件获取子组件输入值
你的问题核心是子组件独自维护输入状态,导致父组件无法直接获取更新后的值。解决思路是把状态管理从子组件转移到父组件,让子组件成为受控组件,所有输入变更都通知父组件,这样父组件就能统一掌控所有数据。
1. 改造BasicCard子组件
移除子组件内部的value状态,改为接收父组件传递的value和onValueChange回调,TextField的输入变更直接通过回调通知父组件:
import * as React from 'react'; import Card from '@mui/material/Card'; import CardContent from '@mui/material/CardContent'; import TextField from '@mui/material/TextField'; export default function BasicCard({ dataObj, value, onValueChange }) { // 当传入的dataObj更新时,同步父组件的状态(比如初始化或外部数据更新时) React.useEffect(() => { onValueChange(dataObj.weight); }, [dataObj, onValueChange]); return ( <Card sx={{ minWidth: 75 }}> <CardContent> <TextField type="number" value={value} // 把输入值转成数字后传递给父组件 onChange={(e) => onValueChange(Number(e.target.value))} /> </CardContent> </Card> ); }
2. 父组件实现数据管理与值获取
父组件维护所有卡片的状态,渲染子组件时传递对应的值和更新回调,同时添加按钮触发值获取逻辑:
import * as React from 'react'; import BasicCard from './BasicCard'; import Button from '@mui/material/Button'; export default function ParentComponent() { // 原始数据源 const initialMetrics = [ { "metric": "AAA", "weight": 10}, { "metric": "BB", "weight": 20}, { "metric": "CCC", "weight": 30}, ]; // 父组件维护所有卡片的当前值,用metric作为唯一标识 const [cardValues, setCardValues] = React.useState( initialMetrics.map(item => ({ metric: item.metric, currentWeight: item.weight })) ); // 更新单个卡片的权重值 const updateCardWeight = (metric, newWeight) => { setCardValues(prevValues => prevValues.map(item => item.metric === metric ? {...item, currentWeight: newWeight} : item ) ); }; // 点击按钮获取所有卡片的当前值 const getAllValues = () => { // 整理成和原始数据一致的格式 const allCurrentData = cardValues.map(item => ({ metric: item.metric, weight: item.currentWeight })); console.log('所有卡片当前值:', allCurrentData); // 这里可以添加后续逻辑,比如提交到服务器、存储到本地等 }; return ( <div style={{ display: 'flex', gap: '16px', padding: '20px' }}> {cardValues.map(item => ( <BasicCard key={item.metric} dataObj={{ metric: item.metric, weight: item.currentWeight }} value={item.currentWeight} onValueChange={(newVal) => updateCardWeight(item.metric, newVal)} /> ))} <Button variant="contained" onClick={getAllValues} style={{ alignSelf: 'center' }} > 获取所有值 </Button> </div> ); }
关键说明
- 状态提升:把原本子组件内部的输入状态移到父组件,父组件成为所有数据的单一数据源,确保数据的一致性和可访问性。
- 受控组件:子组件的TextField值完全由父组件传递的
value控制,输入变更通过onValueChange回调同步到父组件状态。 - 唯一标识:用
metric作为每个卡片的唯一key,确保更新时能精准定位到对应的卡片数据。
内容的提问来源于stack exchange,提问作者SM079
相关产品推荐
相关产品推荐

