为映射对象设置独立状态值:解决Material UI Rating组件同值问题
问题描述
我基于映射对象构建了一个使用Material UI组件的星级评分组件,但点击任意星级评分时,所有评分都显示相同的值。如何让每个星级评分根据选择拥有独立的数值,使每个评分区域展示自身的对应值?
原代码
import * as React from "react"; import Rating from "@mui/material/Rating"; import Box from "@mui/material/Box"; import "./styles.css"; const data = [ { id: 1, label: "Do you like" }, { id: 2, label: "How do you use" }, { id: 3, label: "Do you dislike" } ]; export default function HoverRating() { const [value, setValue] = React.useState(2); return ( <Box sx={{ width: 200, alignItems: "center" }}> {data.map((rate, id) => ( <div> <p>{rate.label}</p> <div className="rating"> <Rating value={rate.value} max={10} onChange={(event, newValue) => { setValue(newValue); }} /> <p>{value}</p> </div> </div> ))} </Box> ); }
解决方案
问题核心是你用了单个状态变量value存储所有评分的值,导致所有评分组件共用同一状态,点击任意一个都会同步更新所有显示。要实现独立控制,需要给每个评分项分配独立状态:
- 改用多状态存储:用对象保存每个评分项的对应值,以数据中的
id作为区分键 - 绑定对应状态到组件:每个
Rating组件的value绑定到对应id的状态值 - 精准更新状态:在
onChange时仅更新当前评分项对应的状态值
修改后的代码:
import * as React from "react"; import Rating from "@mui/material/Rating"; import Box from "@mui/material/Box"; import "./styles.css"; const data = [ { id: 1, label: "Do you like" }, { id: 2, label: "How do you use" }, { id: 3, label: "Do you dislike" } ]; export default function HoverRating() { // 初始化状态为对象,每个id对应初始值2 const [values, setValues] = React.useState( data.reduce((acc, item) => ({ ...acc, [item.id]: 2 }), {}) ); return ( <Box sx={{ width: 200, alignItems: "center" }}> {data.map((rate) => ( <div key={rate.id}> {/* 添加唯一key,符合React列表渲染规范 */} <p>{rate.label}</p> <div className="rating"> <Rating value={values[rate.id]} max={10} onChange={(event, newValue) => { // 更新对应id的状态值,保留其他项状态不变 setValues(prev => ({ ...prev, [rate.id]: newValue })); }} /> <p>{values[rate.id]}</p> </div> </div> ))} </Box> ); }
关键改动说明
- 将单个
value状态改为values对象,每个评分项的id作为键存储对应值 Rating组件的value改为values[rate.id],绑定到当前项的独立状态onChange时使用函数式更新,仅修改当前id对应的状态值,不影响其他评分项- 给映射的div添加
key={rate.id},避免React列表渲染警告
内容的提问来源于stack exchange,提问作者Briitz
相关产品推荐
相关产品推荐

