React中Checkbox关联数组调用splice删除非末尾元素失效问题
问题根因
verify函数遍历逻辑错误:循环中只要第一个元素id不匹配就直接返回false,不会继续遍历后续数组元素,只有数组首位的元素能被正确匹配到,这是功能异常的核心原因。- 直接修改state原数组:
let newlist = filtergenres属于引用赋值,后续对newlist的splice、unshift操作都是直接修改原state数组,不符合React state不可变的更新原则,可能导致状态更新不触发重渲染等异常。 - 全局
index变量存在副作用风险,跨函数共享变量容易出现值被意外覆盖的问题。
修复代码
仅需修改verify和changeValue两个函数即可,修改后完整逻辑如下:
import React, { useState, useEffect } from 'react'; import { Dialog, DialogTitle, DialogContent, makeStyles, ListItemSecondaryAction } from '@material-ui/core'; import { Button, ButtonToolbar } from 'react-bootstrap'; import Grid from '@material-ui/core/Grid'; import * as FaIcons from 'react-icons/fa'; import './FilterPopup.css' import { filterData } from './filterData'; import { genresData } from './genresData' export default function Filter(props) { const { title, children, openPopup, setOpenPopup, genres, setGenres } = props; const [filtergenres, setFilterGenres] = useState([]); function verify(elem) { // 改用findIndex查找匹配元素的索引,找不到返回-1 return filtergenres.findIndex(obj => obj.id === elem) } function changeValue(elem) { const matchIndex = verify(elem) // 拷贝原数组生成新数组,不直接修改原state let newlist = [...filtergenres] if (matchIndex > -1) { // 存在则删除对应位置元素 newlist.splice(matchIndex, 1) } else { // 不存在则添加元素 newlist.unshift({ id: elem, value: elem }) } setFilterGenres(newlist) } return ( <Dialog open={openPopup} className='filterDialog' maxWidth="md"> <DialogTitle> <div className='popupTitle'> Filter </div> <Button className='popupCloseBtn' onClick={() => { setOpenPopup(false) }}> <FaIcons.FaTimes /> </Button> </DialogTitle> <DialogContent dividers> <form className='pop-up-forms'> <label className='popuppart'> Sort By: <select className='filter-sort'> {filterData.map((item, index) => { return ( <option key={index} value={item.value}>{item.title}</option> ) })} </select> <Button className='popupSearchSubmitBtn' onClick={() => { }}> submit </Button> </label> <label className='popuppart'> Include Adult: <input className='filterchkbox' name="isAdult" type="checkbox" /> </label> <label className='filterGenres'> Genres: <Grid container spacing={1} direction="row" justify="center" alignItems="center"> {genresData.map((item, index) => { return ( <Grid item key={index}> <label className='genresLabel'> {item.name} <input className='filterchkbox' name="isAdult" type="checkbox" value={item.id} onClick={() => { changeValue(item.id) }} /> </label> </Grid> ) })} </Grid> </label> </form> </DialogContent> </Dialog > ) }
内容的提问来源于stack exchange,提问作者Ndifreke James Okpo
相关产品推荐
相关产品推荐

