ReactJS:如何从子组件的状态中获取选中值?
解决方案:获取Select组件选中值的两种方式
推荐方案:状态提升至App组件(符合React单向数据流)
React中,当多个组件需要共享或访问同一状态时,状态提升是标准做法。把Select的选中状态移到App组件后,父组件可以直接拿到选中值,点击按钮打印就很简单。
修改后的App组件代码:
import React, { useState } from "react"; import { Button } from "@mui/material"; import SelectVariant from "./Components/SelectVariant"; import { category } from "./data"; function App() { // 将选中状态托管在App组件中 const [selectedCategory, setSelectedCategory] = useState(''); // 按钮点击事件:打印选中值 const handleGetClick = () => { console.log('当前选中值:', selectedCategory); }; return( <div> <SelectVariant values={category} name="Category" // 传递当前选中值给子组件 value={selectedCategory} // 传递状态更新函数给子组件 onChange={setSelectedCategory} /> <Button variant="contained" onClick={handleGetClick}>Get</Button> </div> ) } export default App;
修改后的SelectVariant组件代码:
将组件改为受控组件,不再维护内部状态,完全依赖父组件传入的value和onChange:
import * as React from 'react'; import InputLabel from '@mui/material/InputLabel'; import MenuItem from '@mui/material/MenuItem'; import FormControl from '@mui/material/FormControl'; import Select from '@mui/material/Select'; export default function SelectVariant(props) { const handleChange = (event) => { // 调用父组件传递的onChange函数更新状态 props.onChange(event.target.value); }; const menuItems = props.values.map(ele => ( <MenuItem key={ele} value={ele}>{ele}</MenuItem> )) return ( <FormControl sx={{ m: 1, minWidth: 120 }} size="small"> <InputLabel id="demo-select-small">{props.name}</InputLabel> <Select labelId="demo-select-small" id="demo-select-small" value={props.value} label={props.name} onChange={handleChange} > {menuItems} </Select> </FormControl> ); }
备选方案:使用Ref访问子组件内部状态(不推荐)
如果不想修改状态结构,可以通过useRef和forwardRef获取子组件的内部状态,但这种方式会增加组件耦合度,不利于后续维护,仅适合临时场景。
修改后的App组件代码:
import React, { useRef } from "react"; import { Button } from "@mui/material"; import SelectVariant from "./Components/SelectVariant"; import { category } from "./data"; function App() { const selectRef = useRef(null); const handleGetClick = () => { // 通过ref访问子组件暴露的状态 console.log('当前选中值:', selectRef.current?.category); }; return( <div> <SelectVariant ref={selectRef} values={category} name="Category" /> <Button variant="contained" onClick={handleGetClick}>Get</Button> </div> ) } export default App;
修改后的SelectVariant组件代码:
使用forwardRef和useImperativeHandle暴露内部状态:
import * as React from 'react'; import InputLabel from '@mui/material/InputLabel'; import MenuItem from '@mui/material/MenuItem'; import FormControl from '@mui/material/FormControl'; import Select from '@mui/material/Select'; // 用forwardRef包裹组件,允许父组件传递ref const SelectVariant = React.forwardRef((props, ref) => { const [category, setCategory] = React.useState(''); // 暴露指定属性给父组件的ref React.useImperativeHandle(ref, () => ({ category })); const handleChange = (event) => { setCategory(event.target.value); }; const menuItems = props.values.map(ele => ( <MenuItem key={ele} value={ele}>{ele}</MenuItem> )) return ( <FormControl sx={{ m: 1, minWidth: 120 }} size="small"> <InputLabel id="demo-select-small">{props.name}</InputLabel> <Select labelId="demo-select-small" id="demo-select-small" value={category} label={props.name} onChange={handleChange} > {menuItems} </Select> </FormControl> ); }); export default SelectVariant;
方案对比
- 状态提升:符合React单向数据流,组件解耦,便于维护和扩展,优先选择。
- Ref访问:组件耦合度高,子组件内部状态变化会影响父组件,仅在特殊场景下使用。
内容的提问来源于stack exchange,提问作者FloydK
相关产品推荐
相关产品推荐

