Thinker
Thinker

Reputation: 5366

react-table iterating over object array to print values in a column

I am using react-table to generate tables(https://react-table.js.org/#/story/readme). I have a state defined as following:

this.state = {

    sampleTable:[
        {author: 'Mac', books: [{title:'One', price: 20}, {title:'Two', price: 20}]},
        {author: 'Rick', books: [{title:'Three', price: 20}, {title:'Four', price: 20}]}
    ],

    sampleTableColumns:[
        {Header: 'Author', accessor: 'author'},
        {Header: 'Books', accessor: 'books.title'},
    ],
};

And I am trying to make table as following:

<ReactTable
    className="-highlight"
    data={this.state.sampleTable}
    columns={this.state.sampleTableColumns}
    defaultPageSize={10}
/>

However in the books column I see nothing. I am not sure how am I supposed to iterate over books array so that I can print say book titles in books column?

Upvotes: 8

Views: 23198

Answers (5)

nkmuturi
nkmuturi

Reputation: 456

I believe Shivam Modi answered it. Using TypeScript his solution could be rendered something like (using built-in row selector):

{
        Header: "Books",
        accessor: "books",
        Cell: ({ row }) => {
            return (
                 row.original.books
                    .map((book: Book) => (
                        <div key={book.id}>
                            <h4>{book.name}</h4>
                        </div>
                    ))
            );
        },
    },

Upvotes: 2

deathfry
deathfry

Reputation: 744

Well, I am too late for the party but all above doesn't work for me and I tried to use ES6 syntax. I have requested data in array, so here we go (I renamed variables):

  export const returnPreparedField = (array) => {
    const newArray = [];

    for (let arrayValue of array) {

        const newElement = {
            id: "element",
            header: element,
            accessor: data => data.element.find(elementToFind => (elementToFind.name === element))?.value,
            show: true,
            width: 100
        };

        newArray.push(newElement);
    }
    return newArray;
};

Upvotes: 0

Shivam Modi
Shivam Modi

Reputation: 379

It's simple without using any dependencies like lodash...

You just need to use React-table Cell attribute

sampleTableColumns:[
{
    Header: 'Author',
    accessor: 'author',
},
{
    Header: 'Books',
    accessor: 'books',
    Cell: (props) => {
        const { sampleTable} = props.original;
        return (
            { sampleTable.books.map( (book) =>(<h4>{book.title}</h4>)) }
        );
    },
},],

Upvotes: 4

Thinker
Thinker

Reputation: 5366

I had to write my accessor like following:

sampleTableColumns:[
    {
        Header: 'Author',
        accessor: 'author',

    },
    {
        Header: 'Books',
        id:'books',
        accessor: data => {
            let output = [];
            _.map(data.books, book => {
                output.push(book.title);
            });
            return output.join(', ');
        },
    },
],

Upvotes: 14

Stephen L
Stephen L

Reputation: 2339

Your books data is an array and I don't believe react-table knows how to render those by default. You can instead supply your own render function in the sampleTableColumns for that cell, which would look something like:

sampleTableColumns:[
    {Header: 'Author', accessor: 'author'},
    {
      Header: 'Books', 
      accessor: 'books'
      render: (rowInfo) => {
        return (
          <span>
           {rowInfo.value.map(book => (<span>{book.title}</span>))}
          </span>
      },
    },
],

Upvotes: 0

Related Questions