首页 > 解决方案 > React splice 无法与 Checkbox 中的数组一起正常工作

问题描述

我有一个允许多个复选框的表单。当用户单击复选框时,应该将值添加到对象数组中,并且当用户取消单击时,将从数组中删除该值,但这不起作用,除非该值是最后添加到数组中的。

编码:

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([]);

    var index;

    function verify(elem) {
        for (var i = 0; i < filtergenres.length; i++) {
            var obj = filtergenres[i];
            if (obj.id == elem) {
                console.log(obj);
                index = i;
                console.log(index);
                return true;
            } else {
                return false;
            }
        }
    }

    function changeValue(elem) {

        console.log(elem);

        let newlist = filtergenres;

        if (verify(elem)) {
            console.log(index);
            newlist.splice(index, 1);
            setFilterGenres(newlist);
            console.log(newlist);
            console.log(filtergenres);
        } else {
            newlist.unshift({
                id: elem,
                value: elem
            });
            setFilterGenres(newlist);
            console.log(newlist);
            console.log(filtergenres);
        }
    }

    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 >
    )
}

这页纸:

BingeHUB 主页

在照片中,我按以下顺序单击了选项:

动作(值:28)、冒险(值:12)、动画(值:16)、喜剧(值:35)然后我取消了动画。但是代码再次添加了 16。如果我再次单击动画以重新检查它,那么它将删除它刚刚添加的 16。

标签: javascriptarraysreactjssplice

解决方案


splice并且unshift不要以不可变的方式编辑数组(参考保持不变)。React 的变更检测机制仅由新引用触发。如果您仍想使用splice并且unshift可以先创建数组的副本 ( const clone = [...newlist];),请在其上调用函数,然后将其传递给setFilterGenres. 这种方式引用将改变,React 将能够看到这种变化。


推荐阅读