Skip to content

row selection not working for grouped rows (flat data) #4879

Closed

Description

@csantos-nydig

Describe the bug

row-selection in the group rows are not correctly reacting to their sub-rows row-selection state

I'm not sure if it's the same issue as #4878 - but better to track separately.

Your minimal, reproducible example

https://codesandbox.io/s/row-grouping-8twj0x

Steps to reproduce

  1. Go to https://codesandbox.io/s/row-grouping-8twj0x
  2. Expand "relationship" group
  3. Select the first child in that group
  4. ✅ Notice the "relationship" group being "indeterminate"
    image
  5. Select the other 2 children in that group
  6. 🛑 Notice the "relationship" row checkbox is "unchecked", when it should be "checked"
    image

Possibly the same issue

  1. Go to the same codesandbox https://codesandbox.io/s/row-grouping-8twj0x
  2. Expand the two groups
  3. Select the checkbox from the column header (to select all)
  4. 🛑 Notice the parent row checkboxes aren't checked
    image

Expected behavior

As a user, I expected the parent row to react to the row-selection status of its children, regardless on how they are selected/unselected:

  • some sub-rows selected: parent row "indeterminate"
  • no sub-rows selected: parent row "unchecked"
  • all sub-rows selected: parent row "checked"

How often does this bug happen?

Every time

Screenshots or Videos

No response

Platform

  • Browser: All
  • OS: All

Happens in codesandbox

react-table version

v8.9.1

TypeScript version

N/A - whatever codesandbox uses

Additional context

No response

Terms & Code of Conduct

  • I agree to follow this project's Code of Conduct
  • I understand that if my bug cannot be reliable reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.

Activity

  1. VincEnterprise commented on Dec 20, 2023

    @VincEnterprise

    bump

  2. Radomir-Drukh commented on Nov 21, 2025

    @Radomir-Drukh

    Here is my solution

    import * as React from 'react';
    
    import type {RowSelectionState, Updater} from '@tanstack/react-table';
    
    interface RowSelectionProps<T> {
        rowSelection: RowSelectionState;
        setRowSelection: React.Dispatch<React.SetStateAction<RowSelectionState>>;
        tableData: T[];
        item: T;
        getSubRows: (item: T) => T[] | undefined;
        getRowId: (row: T) => string;
    }
    
    const processItemSelection = <T>({
        rowSelection,
        item,
        getSubRows,
        getRowId,
    }: Omit<RowSelectionProps<T>, 'setRowSelection' | 'tableData'>): boolean => {
        let isSelected = true;
    
        const itemId = getRowId(item);
    
        const subRows = getSubRows(item) ?? [];
    
        if (subRows.length > 0) {
            subRows.forEach((subRow) => {
                const isSubRowSelected = processItemSelection({
                    item: subRow,
                    rowSelection,
                    getSubRows,
                    getRowId,
                });
    
                if (!isSubRowSelected) {
                    isSelected = false;
                }
            });
        } else {
            isSelected = rowSelection[itemId] === true;
        }
    
        if (isSelected) {
            rowSelection[itemId] = true;
        } else if (itemId in rowSelection) {
            delete rowSelection[itemId];
        }
    
        return isSelected;
    };
    
    export const useRowSelectionFixedHandler = <T>({
        rowSelection,
        setRowSelection,
        tableData,
        getSubRows,
        getRowId,
    }: Omit<RowSelectionProps<T>, 'item'>) => {
        const fixedRowSelectionHandler = React.useCallback(
            (rowSelectionUpdater: Updater<RowSelectionState>) => {
                const rowSelectionUpdated =
                    typeof rowSelectionUpdater === 'function'
                        ? rowSelectionUpdater(rowSelection)
                        : rowSelectionUpdater;
    
                tableData.forEach((item) => {
                    processItemSelection({
                        item,
                        rowSelection: rowSelectionUpdated,
                        getSubRows,
                        getRowId,
                    });
                });
    
                setRowSelection(rowSelectionUpdated);
            },
            [rowSelection, setRowSelection, tableData, getSubRows, getRowId],
        );
    
        return fixedRowSelectionHandler;
    };
    
  3. KevinVandy commented on Aug 3, 2026

    @KevinVandy
    Member

    fixed in v9

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions