I am trying to build a product list with selectAll functionality but when I'm clicking on selectAll checkBox the state[checkBoxes Array] isn't reflecting the other checkboxes after calling handleCheck() method. I have also used useEffect() with chkAll as a dependency, but the problem didn't resolve. Please help me to resolve this problem
Whole Code...
import React, { useEffect, useState } from 'react'
import { Card,Container, Row, Col,Button,Media,Form,Tooltip } from "react-bootstrap";
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faSearch,faFilter, faTimes,faEdit } from '@fortawesome/free-solid-svg-icons';
import Checkbox from '../CustomCheckbox/CustomCheckbox';
import './ProductListData.css'
const styles = {
mediaItem: {
// margin:'1rem',
// border: "1px solid gray",
backgroundColor: "#f5f5f5",
},
mediaItemButtons: {
paddingTop: "5px",
paddingBottom: "5px"
}
};
export default function P2({products,allCheck,setAllCheck}) {
var f=0;
const [state,setState]=useState({
checkedBoxes:[],
})
const [chkBox,setChkBox]=useState(false)
const [q,setQ]=useState("")
const Search=(products)=>{
return products.filter(product=>
product.name.toLowerCase().indexOf(q.toLowerCase())!==-1 || //str.includes(PATTERN)
product.price.toLowerCase().indexOf(q.toLowerCase())!==-1 ||
product.manufacturer.toLowerCase().indexOf(q.toLowerCase())!==-1
);
// return products.filter(product=>product.name.toLowerCase()===q.toLowerCase())
}
const handleCheck=(e,product)=>{
let itemName=e.target.name;
let checked=e.target.checked;
if(itemName==='checkAll'){
if(checked){
setChkBox(true)
setState(prevState=>{
let {checkedBoxes}=prevState;
let categories = new Set(checkedBoxes)
for(var i=0;i<products.length;i++)
categories.add(products[i].id)
checkedBoxes=Array.from(categories)
return {...prevState.checkedBoxes, checkedBoxes: checkedBoxes }
})
console.log("Checked",state.checkedBoxes);
}
else{
setChkBox(false);
setState(prevState=>{
let {checkedBoxes}=prevState;
checkedBoxes.splice(0, checkedBoxes.length)
return {...prevState.checkedBoxes, checkedBoxes: checkedBoxes };
});
console.log("UnChecked",state.checkedBoxes);
}
}
else if(checked) {
var arr = state.checkedBoxes;
arr.push(product.id);
setState(state=>({...state,checkedBoxes:arr}));
} else {
let products = state.checkedBoxes.splice(state.checkedBoxes.indexOf(product.id), 1);
setState(state=>({...state,checkedBoxes:products}));
}
}
return (
<>
<div className='products'>
<Card className='cardpl'>
<Card.Header className='header'>
<div className='header-filter'>
<input
// id={id}
name='checkAll'
type="checkbox"
checked={chkBox}
onChange={(e)=>handleCheck(e)}
/>
{/* <Checkbox
number={1000}
isChecked={false} lebal={'Chk'}/> */}
<div className='search-bar' >
<FontAwesomeIcon icon={faSearch} />
<input type="text" value={q} placeholder="Search Products" onChange={(e)=>{setQ(e.target.value)}}/>
</div>
<div className='filter-icon'>
<Button className='filter-button' style={{background:'transparent',color:'#3c44b1',border:'none',boxShadow:'none'}}> <FontAwesomeIcon icon={faFilter} /></Button>
</div>
{/* <FontAwesomeIcon icon={f}/> */}
</div>
</Card.Header>
<Card.Body className='productListBody overflow-auto custom-scrollbar-css '>
<p>{products.length!==0?Search(products).map((product,id)=>(
<div style={{display:'flex',alignItems:'center',border:'1px solid #dee2e6',margin:'.5rem'}}>
{/* <Checkbox
number={id}
isChecked={false}
/> */}
<input
id={id}
type="checkbox"
name={product.id}
value={product.id}
checked={state.checkedBoxes.find((p) => p.id === product.id)}
onChange={(e) => handleCheck(e, product)}
/>
<Media key={product.id}
style={{padding:'.5rem',flex:'1'}} className={styles.mediaItem}>
<img
width={100}
height={100}
className="align-self-center mr-3"
src="https://i5.walmartimages.com/asr/e73e1252-642c-4473-93ea-fd3b564a7027_1.3e81ea58fa3042452fe185129a4a865f.jpeg?odnWidth=undefined&odnHeight=undefined&odnBg=ffffff"
alt="Generic placeholder"
/>
<Media.Body className={styles.mediaBody}>
<p><b>{product.name}</b></p>
<Row className='product-row'>
<Col className='product-col' xs={2}>
<strong>By:</strong>{product.manufacturer}
</Col>
<Col className='product-col' xs={2}><b>4.5</b>/5</Col>
<Col className='product-col' xs={2}>
<strong>${product.price}</strong>
</Col>
<Col className='product-col' xs={2}><strong>Stock</strong>{product.stock}</Col>
<Col xs={2} style={{minWidth:'10rem'}}>
<div className='action-button'>
<Button variant="primary" size="sm">
<FontAwesomeIcon icon={faEdit}/>
</Button>
<Button variant="danger" size="sm">
<FontAwesomeIcon icon={faTimes}/>
</Button>
</div>
</Col>
</Row>
</Media.Body>
</Media></div>)):null}
</p>
</Card.Body>
</Card>
</div>
</>
)
}

Issue
It seems your
checkedBoxesstate is an array of ids.but your render code is searching this array as if they were objects with an
idproperty.Solution
Just check if the
checkedBoxesarray includes the product idSide Note: Console logging state right after an enqueued update (i.e.
console.log("Checked",state.checkedBoxes);will only log the state from the current render cycle, not what you are updating it to for the next render cycle. You can use anuseEffecthook with a dependency on the chunk of state you want to log after it's updated.