0

I am trying to filter the list of array of objects from the Material UI Autocomplete, based on mutiple conditions. However the onchange method is only returning the first state. By that i mean;

-- const array = [1, 2, 2, 3, 4, 4]

-- filtrering 2 //return 2, 2

-- User change condition to filtrering 2 and 3 // null

//Array for checkbox
const races = [
  'Akita',
  'American Bulldog',
  'Barbet',
  'Beaglier',
  'Cavapoo',
  'Chihuahua',
  'Dachshund',
  'Goldador',
  'Virginia Andrews',
  'Golden Retriever',
];

const class = () => {
//Array for list data 
const [array, setArray] = useState([ // this only change in the first render
  { id: 1, title: 'Akita from place1', race: "Akita" },
  { id: 2, title: 'Akita from place2', race: "Akita" },
  { id: 3, title: 'Akita from place3', race: "Akita" },
  { id: 4, title: 'Chihuahua from place4', race: "Chihuahua" },
  { id: 5, title: 'Cockapoo from place5', race: "Cockapoo" },
  { id: 6, title: 'Dachshund from place6', race: "Dachshund" },
  { id: 7, title: 'Dutch Shepherd from place7', race: "Dutch Shepherd" },
  { id: 8, title: "Bulldog from place8", race: "Bulldog" },
  { id: 9, title: 'Goldador from place9', race: "Goldador" },
])

//Array for filter
const [filteredArray, setFilteredArray]= useState<any | null>(array || null) // use this to print 


//Onchange for material ui autocomplete checkbox
    const handleArrayChanges = (event, value) => {
      if (value) {  
        const data = array.filter(data => data.race.includes(value)).map(filteredName => {
          return filteredName
        })
        setFilteredArray(data);
      } else {
        const data2 = array.filter(data => data.race.includes(value)).map(filteredName => {
          return !filteredName;  
        })

        setFilteredArray(data2)
      }
      console.log(value)
      console.log(data)
   };

 return (
<Grid container xs={10} sm={10} md={10} lg={12} xl={8} spacing={3} style={{marginTop: 50}}>
 <Autocomplete
              multiple
              id="checkboxes-tags-demo"
              options={races}
              disableCloseOnSelect
              onChange={handleArrayChanges}
              getOptionLabel={(option) => option}
              renderTags={(value, getTagProps) => {
                const numTags = value.length;
                const limitTags = 1;
        
                return (
                  <>
                    {value.slice(0, limitTags).map((option, index) => (
                      <Chip
                        {...getTagProps({ index })}
                        key={index}
                        label={option}
                      />
                    ))}
        
                    {numTags > limitTags && ` +${numTags - limitTags}`}
                  </>
                );
              }}
              PaperComponent={({ children }) => (
                <Paper style={{ width: 1000 }}>{children}</Paper>
              )}
              renderOption={(props, option, { selected }) => (
                <li {...props}>
                  <Checkbox
                    icon={icon}
                    checkedIcon={checkedIcon}
                    checked={selected}
                  />
                  {option}

                </li>
              )}
              style={{ width: 300 }}
              renderInput={(params) => (
                <TextField {...params} label="Search for dog breeds"
                style={{backgroundColor: "#EEEEEE"}} variant="outlined" size="medium" 
                />
              )}      
            />
    {filteredArray?.map((data, _index) => (
        <Grid item xs={3}>
        <Card key={_index} sx={{ maxWidth: 300 }}>
      <CardMedia component="img" height="200" image={image} alt="green iguana" />
      <CardContent>
        <Typography gutterBottom variant="h5" component="div">
          {data.title}
        </Typography>
        <Typography variant="body2" color="text.secondary">
          {data.race}
        </Typography>
      </CardContent>
      <CardActions>
        <Button size="small">Share</Button>
        <Button size="small">Learn More</Button>
      </CardActions>
    </Card>
      </Grid>

 
    ))}
</Grid>

I know the usetate is pushing current value, which make the next condition return nothing, because there is no data. But i don't know how to solve this.

https://codesandbox.io/s/infallible-beaver-zdvn7?file=/src/App.js

2
  • In handleArrayChanges, what is the type of the value parameter? Additionally, in array.filter(data => data.race.includes(value)), what is the type of race? It feels like you're calling String.prototype.includes() with an array, which would be weird! I wish I could help you further, but you really should provide us with a code-sandbox or something similar if you want us to untangle code like this. Commented Dec 17, 2021 at 20:21
  • Of course, I have updated now with a code-sandbox Commented Dec 17, 2021 at 21:36

1 Answer 1

1

EDIT: Codesandbox with working example: https://codesandbox.io/s/delicate-grass-feqyn

You need to turn your filter statement around:

try replacing

 .filter((data) => data.race.includes(value))

with

.filter((data) => value.includes(data.race))
Sign up to request clarification or add additional context in comments.

2 Comments

Ahh that worked, thank you. I have another question if you dont mind. If i do this it works as intended but if i uncheck the checkboxes, it won't return to the initial state. Any thoughts about the approach?
Yes, i put in a sandbox where it is fixed. Basically you need to have you init state in a const outside your component. Please mark answer as correct if it helped you :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.