0

UI image So, You see that UI in above image..., I'm trying to replicate some functionality of G-Mail - Selecting multiple items or All items. When I try to select all(the purple chkbox)... my child components don't re-render checkboxes even though their state variable selectedList gets updated. I need to check all the boxes on selectAll==true

I feel like I'm doing something wrong with .map()... it is ensured that id in map is always unique and also it is the key attribute for child components while mapping

My main component Table:

export default function Table() {
    const [selectAll, setSelectAll] = useState(false)
    //gave a dummy id:0 beacause React is throwing Uncontrolled to controlled component error as an empty {} is nothing but undefined
    const [selectedList, setSelectedList] = useState({ id: 0 })
    console.log(selectedList)
    
    useEffect(()=>{
        let newSelectedList = {}
        if(selectAll){
            dataList.forEach(ele =>  newSelectedList[ele.id]=1);
        }else{
            dataList.forEach(ele =>  newSelectedList[ele.id]=0);
        }
        setSelectedList(newSelectedList)
    },[selectAll])

    return <div>
        <ActionBar />
        <div className="overflow-x-auto w-full">
            <table className="table w-full">
                {/* HEAD */}
                <thead>
                    <TableHeadingRow select selectAll={selectAll}
                        setSelectAll={setSelectAll} />
                </thead>
                {/* BODY */}
                <tbody>
                    {
                    dataList.map(data =>
                        <TableRow key={data.id} data={data}
                            selectedList={selectedList} setSelectedList={setSelectedList} />)
                    }
                </tbody>
                {/* FOOT */}
                <tfoot>
                    <TableHeadingRow />
                </tfoot>
            </table>
        </div>
    </div>
}

In above code, selectAll keeps track of purple checkbox and selectedList is an object of all unique ids of child components as keys and 0 or 1 as values

I try to render checkboxes in child components when their id in selectedList has a value 1

selectedList is passed as prop to child component

Child component TableRow(the one which doesn't re-render):

function TableRow({ data, selectedList, setSelectedList }) {
    const { id, name, branch, address, phone, mail } = data
    function handleChange() {
        setSelectedList(prev => {
            return { ...prev, [id]: 1 ^ prev[id] }
        })
    }
    return <tr>
        <th>
            <label>
                <input type="checkbox" className="checkbox checkbox-secondary"
                    checked={selectedList.id} onChange={handleChange} />
            </label>
        </th>
        <td>
            <div className="flex items-center space-x-3">
                <div>
                    <div className="font-bold">{name}</div>
                    <div className="text-sm opacity-50">{branch}</div>
                </div>
            </div>
        </td>
        <td>{address}</td>
        <td>{phone}</td>
        <td>{mail}</td>
    </tr>
}

Ignore handleChange in child component, it's for singly selecting elements and works fine... It isn't related to this question anyways

On console.log(selectedList), I do get updated values of all ids to 1 but state of child components remain unchanged. Please help me figuring this out and let me know what I'm doing wrong. Any help is massively appreciated!

Prithvi Reddy
  • 11
  • 1
  • 5
  • 1
    `checked={selectedList.id}` should be `checked={selectedList[id]}` – CertainPerformance Jun 25 '22 at 03:20
  • Wow, it worked, I didn't know that would make a difference, Me dumb af coming from python. But I'm curious to know what made the difference? don't they act as same? – Prithvi Reddy Jun 25 '22 at 03:22
  • Ok, understood, that made all the difference https://dmitripavlutin.com/access-object-properties-javascript/#2-square-brackets-property-accessor Thanks again for such a quick response – Prithvi Reddy Jun 25 '22 at 03:24
  • @CertainPerformance This caused me another warning i don't even know why, It says `next-dev.js?3515:25 Warning: A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component.` whereas it is a controlled component all the time – Prithvi Reddy Jun 26 '22 at 01:16
  • Random guess, perhaps `checked={undefined}` makes React think it's uncontrolled. Try `checked={selectedList[id] ?? false}`, I'd be curious to see if that fixes it – CertainPerformance Jun 26 '22 at 01:17
  • @CertainPerformance You're insane, its fixed... but idk why at first place it was undefined as I defined it. Or I think before my useEffect runs, that component is rendering mb. Thnx for your time a lot – Prithvi Reddy Jun 26 '22 at 01:28

0 Answers0