7

I am using React Table in my project, I don't know how to close other expanded rows when user clicks one expanded, i.e. when first, second, and third rows are all expanded, I want to close all of the three when user click the fourth row.

Can someone tell me how?

Tom
  • 6,325
  • 4
  • 31
  • 55
lletgo
  • 67
  • 1
  • 1
  • 2

6 Answers6

18

For anyone looking for more info about that :

//in component constructor, add state declaration :

this.state = {
    expanded: {}
}

//in component render function - set "expanded" to component state:

expanded={this.state.expanded}

// still in component render() - set an event callback - I prefer to use a dedicated event manager here named handleRowExpanded :

onExpandedChange={(newExpanded, index, event) => this.handleRowExpanded(newExpanded, index, event)}

// then declare an event manager :

   handleRowExpanded(newExpanded, index, event) {
        this.setState({
        // we override newExpanded, keeping only current selected row expanded
            expanded: {[index]: true}
        });
    }

HTH :)

Arnaud Enesvat
  • 351
  • 2
  • 5
  • The key here is to let the parent component (the component actually rendering the react-table) orchestrate the state. +1 for pointing out that expanded={this.state.expanded}. – jacobhobson Oct 04 '18 at 23:38
  • 1
    how to do it in functional component al i see exapanded is read-only, any solutions will help. thank you – Nikhil Gowda Mar 03 '22 at 08:11
9

The way Arnaud Enesvat suggests works for expansion but not to collapse an expanded row back.

I'd suggest his implementation with a change:

handleRowExpanded(rowsState, index) {
  this.setState({
    expanded: {
      [index[0]]: !this.state.expanded[index[0]],
    },
  });
}
3

I've found help from Nathan Zylbersztejn at spectrum.chat/thread/ea9b94dc-6291-4a61-99f7-69af4094e90c :

<ReactTable
    ...
    expanded={this.state.expanded}
    onExpandedChange={(newExpanded, index, event) => {
        if (newExpanded[index[0]] === false) {
            newExpanded = {}
        } else {
            Object.keys(newExpanded).map(k => {
                newExpanded[k] = parseInt(k) === index[0] ? {} : false
            })
        }
        this.setState({
            ...this.state,
            expanded: newExpanded
        })
    }}
/>

I hope it helps somebody.

0
// this line will go into constructor (keep every accordion closed initially)
this.state = {
  expanded: {}
}

// this line will go into react table (will keep only one accordian open at any time)
expanded={this.state.expanded}
onExpandedChange={expandedList => {
    const expanded = {}
    Object.keys(expandedList).forEach(item => {
        const expand = Boolean(expandedList[item] && expandedList[item].constructor === Object)
        expanded[item] = expand
    })
    this.setState({ expanded })
}}
-2

Ok, I figured it out by myself in the end. By dynamically change the "expanded" props of the react-table, I was able to control show only one expanded row each time.

lletgo
  • 67
  • 1
  • 1
  • 2
  • 1
    How do you fix for expand a single row at a time? Please share the code with your fixing. – birendra Aug 23 '18 at 06:42
  • 4
    It's good to answer your own questions, but I think you should post some code here to show whatyou've done. – dwjohnston Aug 24 '18 at 17:25
  • Here is code sample { return ; }} onExpandedChange={(newExpanded, index, event) => this.handleRowExpanded(newExpanded, index, event)} /> – birendra Aug 27 '18 at 07:41
-3
onExpandedChange = (expanded, index, event) => {
    this.setState({ expanded: { [index]: expanded[index] !== false } })
}
Tony Huynh
  • 39
  • 2
  • 8
  • 3
    Could you please add some explanation about *how* and *why* your code snippet provides an answer to the question? Thank you. – deHaar Jul 29 '19 at 10:36
  • @deHaar i google this issue, i found this code, i used it in my project, it worked, i share, if you are react developer, you're looking for solution for this issue, you will know how and why, that's it – Tony Huynh Aug 08 '19 at 02:40