1

I've got a Form that allows multiple check boxes. When a user clicks the checkbox, it is supposed to add the value to an array of objects and when the user unclicks the value is to be removed from the array but this doesn't work unless the value is the last added in the array. When I log the index it only shows 0 on the console regardless of the array size. Pls I need help with this issue I've been stuck for the past 2 days.

The code:

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 (let m = 0; m < filtergenres.length; m++) {
            console.log(m);
            var obj = filtergenres[m];
            console.log(obj);
            if (obj.id === elem) {
                index = m;
                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 >
    )
}
ND-BEAST
  • 67
  • 8
  • My apologies, I didn't mean to make an edit on your post. – PurpSchurp Aug 07 '21 at 19:33
  • Sure looks like you're mutating state when you call `newlist.splice` See https://stackoverflow.com/questions/36326612/how-to-delete-an-item-from-state-array – Wyck Aug 07 '21 at 19:48

1 Answers1

1

I made this a bit more simple, but I could not test it. The idea is to use built in array functions rather than the loops you had. I also moved the console log outside of the function so you can see the state as it is changing. The adjustments I made were to the changeValues function. I stripped away the verify in use of findIndex, and then use splice off of that. We can use push instead of unshift because we are only going to be pushing one thing to the array at a time rather than multiple.

Doing this we also get rid of your variable index, and the setting of it in the function verify, keeping it local to the checkValues scope.

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 (let m = 0; m < filtergenres.length; m++) {
            console.log(m);
            var obj = filtergenres[m];
            console.log(obj);
            if (obj.id === elem) {
                index = m;
                return true;
            } else {
                return false;
            }
        }
    }

    function changeValue(elem) {
        //elem is the id, not the actual element in your case
        console.log(elem);

        let newlist = [...filtergenres];
        let foundIndex = newlist.findIndex(item => item.id == element);
        if (foundIndex > -1) {
            console.log(foundIndex);
            newlist.splice(foundIndex, 1);
            setFilterGenres(newlist);
        } else {
            newlist.push({
                id: elem,
                value: elem
            });
            setFilterGenres(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 >
        )
      }

As I can not test it, let me know if there is anything incorrect, and I can help adjust it as needed.

Although I wouldn't recommend doing it the way you are doing it, you just really need to remove the else statement and just continue on. return false if it gets out of the for loop and return true if its found.

Also a thing you should never do is mutate filtergenres directly. If you are going to be mutating the array, make a deep clone of the object [...filtergenres] which gives you a brand new array, rather than mutating it directly.

Something like this should work?:

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

    return false;
}
PurpSchurp
  • 581
  • 5
  • 14