React中使用.map()方法时如何让Select标签各自独立工作?
问题根因
你当前所有渲染出来的Select组件都绑定了同一个全局状态age,任意Select触发修改时都会更新这个公共状态,所有绑定该状态的组件自然会同步刷新取值,才会出现联动效果。
解决方案
你需要给每行的Select分配独立的状态,这里提供两种常用实现方式:
方案1:将选中值存储到原数组的对应元素属性中
适合需要把选中状态和原业务数据绑定、后续统一提交的场景,修改后代码如下:
// 初始化时给每个item添加默认status属性,也可以在接口返回数据时直接添加 const [actionItemArray, setActionItemArray] = React.useState( // 把下方"原数组"替换成你实际的列表数据源 原数组.map(item => ({...item, status: 'Assigned'})) ); const handleChange = (event, pPk) => { // 仅更新对应行的status值 setActionItemArray(prev => prev.map(item => { if(item.P_PK === pPk) { return {...item, status: event.target.value} } return item })) }; return ( <> { actionItemArray.map(item => ( <tr className={styles.styledTable} key={item.P_PK}> <td className={styles.styledTd}>{item.TITLE}</td> <td className={styles.styledTd}>{item.P_PK}</td> <td className={styles.styledTd}> <Select value={item.status} onChange={(e) => handleChange(e, item.P_PK)} > <MenuItem value='Assigned'>Assigned</MenuItem> <MenuItem value='Processing'>Processing</MenuItem> <MenuItem value='Done'>Done</MenuItem> </Select> </td> <td className={styles.styledTd}>{getUnixTime(item.START_DATE)}</td> <td className={styles.styledTd}>{getUnixTime(item.DUE_DATE)}</td> <td className={styles.styledTd}>{item.owner.FIRST_NAME + item.owner.LAST_NAME}</td> <td className={styles.styledTd}><a className={styles.styledATag}>상세보기</a></td> <td className={styles.styledTd}><a className={styles.styledATag}>수정</a></td> <td className={styles.styledTd}><a className={styles.styledATag} onClick={openDeleteModal}>삭제</a></td> </tr> )) } </> )
方案2:单独用对象存储所有行的选中值
适合不需要改动原数组的场景:
// 以item的唯一标识P_PK为key,存储对应行的选中值 const [selectStatusMap, setSelectStatusMap] = React.useState({}); const handleChange = (event, pPk) => { setSelectStatusMap(prev => ({ ...prev, [pPk]: event.target.value })) }; return ( <> { actionItemArray.map(item => ( <tr className={styles.styledTable} key={item.P_PK}> <td className={styles.styledTd}>{item.TITLE}</td> <td className={styles.styledTd}>{item.P_PK}</td> <td className={styles.styledTd}> <Select // 没有设置过的行取默认值Assigned value={selectStatusMap[item.P_PK] || 'Assigned'} onChange={(e) => handleChange(e, item.P_PK)} > <MenuItem value='Assigned'>Assigned</MenuItem> <MenuItem value='Processing'>Processing</MenuItem> <MenuItem value='Done'>Done</MenuItem> </Select> </td> <td className={styles.styledTd}>{getUnixTime(item.START_DATE)}</td> <td className={styles.styledTd}>{getUnixTime(item.DUE_DATE)}</td> <td className={styles.styledTd}>{item.owner.FIRST_NAME + item.owner.LAST_NAME}</td> <td className={styles.styledTd}><a className={styles.styledATag}>상세보기</a></td> <td className={styles.styledTd}><a className={styles.styledATag}>수정</a></td> <td className={styles.styledTd}><a className={styles.styledATag} onClick={openDeleteModal}>삭제</a></td> </tr> )) } </> )
补充说明:你原有代码中
handleChange里的console.log(age)会打印更新前的旧值,因为React的useState更新是异步操作,要拿到最新值可以直接打印event.target.value。
内容的提问来源于stack exchange,提问作者chiko
相关产品推荐
相关产品推荐

