0

Introduction:

I'm trying to create Table Component which can reusable in nature. It can contain any number of column as per data pass to it through props from parent component.

In order to achieve this, I've created separate function as below to populate JSX element according.

  • renderColumn: It take column name pass as props of array of string from parent.
  • renderBody: This will populate body and TableRow of each row. It will the call renderCell function which will return array of JSX element to be push inside renderBody method.
  • renderCell: This method uses for in to iterate each property of row object and create TableCell element and pushing it to array and returning the array which ideally contain JSX element.

Problem Statement:

However, I'm unable to push JSX element return from renderCell method inside renderBody method.

I did tried console logging the element it return from renderCell method which seems like JSX element only.


Components:

src\components\Table\index.js

import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableCell from '@material-ui/core/TableCell';
import TableContainer from '@material-ui/core/TableContainer';
import TableRow from '@material-ui/core/TableRow';

    renderCell = (row) => {

        var cell = [];

        var i = 1;
        for (var prop in row) {
            if (row.hasOwnProperty(prop)) {
                cell.push(<TableCell key={i} align="right">{ row[prop] }</TableCell>);
                i++;
            }
        }
        console.log(cell)
        return cell;                
    }

    renderBody = () => {
        let rows = this.props.rows

        return (
            <TableBody>
                {rows.map( row => {
                    <TableRow key={row.key}>
                        { this.renderCell(row) } // How do I render Array of JSX Element?
                    </TableRow>
                })}
            </TableBody>
        )
    }

    render() {
        return (
            <TableContainer>
                <Table  aria-label="simple table">
                    { this.renderColumn() }
                    { this.renderBody() }
                </Table>
            </TableContainer>
        );
    }

Below is console.log from renderCell function

[
  {
    $$typeof: Symbol(react.element)
    key: "1"
    props: {align: 'right', children: 1}
    ref: null
    type: {$$typeof: Symbol(react.forward_ref), propTypes: {…}, Naked: {…}, options: {…}, render: ƒ, …}
    _owner: FiberNode {tag: 1, key: null, stateNode: Table, elementType: ƒ, type: ƒ, …}
    _store: {validated: false}
    _self: Table {props: {…}, context: {…}, refs: {…}, updater: {…}, renderColumn: ƒ, …}
    _source: {fileName: '/path/src/components/Table/index.js
  },
]

Complete SandBox link

Data:

[
    {
        "key": 1,
        "launch_date_utc": "2006-03-24T22:30:00.000Z",
        "location": "Kwajalein Atoll",
        "mission_name": "FalconSat",
        "orbit": "LEO",
        "launch_success": false,
        "upcoming": false,
        "rocket_name": "Falcon 1"
    },
    {...}
]

Edit 1: Failed to compile

When trying to wrap inner for loop inside map() function as per following question. It is not compiling by without using renderCell method.

    renderBody = () => {
        return (
            <TableBody>
                {this.props.rows.map( row => {
                    <TableRow key={row.key}>
                        { 
                            for (var prop in row) {
                                if (row.hasOwnProperty(prop)) {
                                    <TableCell  align="right">{ row[prop] }</TableCell>                                   
                                }
                            }
                        }
                    </TableRow>
                })}
            </TableBody>
        )
    }

2 Answers 2

1

To render an array of JSX elements, you should be able to do this:

renderCell = (row) => {
    return row.map(cell => {
       return <TableCell key={i} align="right">{ row[prop] }</TableCell>
    }       
}
Sign up to request clarification or add additional context in comments.

Comments

1

Edit:

<TableBody>
    {(pagination
        ? rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
        : rows
    ).map((row) => {
        return (
            <TableRow
                onClick={onRowClicked(row)}
                hover
                role="checkbox"
                tabIndex={-1}
                key={row[props.rowsUniqueKey]}
            >
                {columns.map((column) => {
                    const value = row[column.id];
                    return (
                        <>
                            <TableCell
                                key={column[props.columnsUniqueKey]}
                                align={column.align}
                            >
                                {column.format && typeof value === 'number'
                                    ? column.format(value)
                                    : value}
                            </TableCell>
                        </>
                    );
                })}
                {/* { enableActions && <TableCell> Actions </TableCell> } */}
            </TableRow>
        );
    })}
</TableBody>

from: Create dynamic action column in React Material UI Table

2 Comments

Failed to compile: Spread children are not supported in React.
@Maqsud I found some examples from stackoverflow.com/questions/60261793/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.