You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中for循环无论数组长度仅执行一次 多选框操作异常求助

问题根因

  1. 校验函数逻辑错误
    你写的verify函数在for循环的第一次迭代就会强制终止:如果数组第一个元素的id和传入的elem相等就返回true,否则直接返回false,完全不会遍历数组剩下的元素。这就是控制台永远只打印索引0、除了最后添加的元素(因为你用unshift插在数组头部,是第一个元素)之外都删不掉的核心原因。

  2. 直接修改状态数组违反React不可变原则
    你执行let newlist = filtergenres时,并没有生成新的数组,只是把newlist指向了原状态数组的引用,后续的splice、unshift操作都是直接修改原有state,会导致React无法正确检测状态变更,出现渲染不同步的问题。

  3. 额外补充:React的状态更新是异步批量执行的,你在setFilterGenres之后立即打印filtergenres,拿到的永远是更新前的旧值,属于正常现象,要查看更新后的状态可以打印新生成的数组,或者通过useEffect监听filtergenres的变化来获取最新值。


修复方案

直接重构复选框切换逻辑,替换原有的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 changeValue(elem) {
      // 先拷贝原数组,生成新的数组引用,符合不可变更新要求
      const newList = [...filtergenres];
      // 查找当前元素在数组中的索引
      const existIndex = newList.findIndex(item => item.id === elem);
      if (existIndex > -1) {
        // 存在就删除对应位置的元素
        newList.splice(existIndex, 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="genres" {/* 这里修正了之前所有分类复选框name都写成isAdult的笔误 */}
                                                type="checkbox"
                                                value={item.id}
                                                onClick={() => { changeValue(item.id) }} />
                                        </label>
                                    </Grid>
                                )
                            })}

                        </Grid>
                    </label>
                </form>
            </DialogContent>
        </Dialog >
    )
}

内容的提问来源于stack exchange,提问作者Ndifreke James Okpo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.09 04:00:01