Search code examples
reactjscomponents

ReactJS passing custom components to a grid


I'm creating a grid(data table) component. It works like that:

const gridOptions = {
    columnDefinitions: [
        {title: 'Test1', component: <ExampleColumnComponent />},
        {title: 'Test2', component: <Example2ColumnComponent />},
    ]
}

<Grid options = {gridOptions} />

Inside Grid component:

records.map((row) => (
    <TableRow key={row.id}>
    {
        props.options.columnDefinitions.map((column, index) => {
        return (
            <TableCell key={index} >
                {column.component}
            </TableCell>);
        })
    </TableRow>))

Inside Grid component i have map which renders components and it work if I don't pass any props to the child components.

export const ExampleColumnComponent = () =>{
    return (<div>TEST lalalalala</div>);
}

But when I use props here it doesn't work:

export const ExampleColumnComponent = (props) =>{
    return (<div>{props.row}</div>);
}

I got a lot of react errors on the runtime such as:

React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: . Did you accidentally export a JSX literal instead of a component

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

I don't know how to pass this row object to the child component inside Grid component and make this work?


Solution

  • You will probably need to use createElement, for example:

    import {createElement} from 'react'
    
    //...
    
    records.map((row) => (
        <TableRow key={row.id}>
        {
            props.options.columnDefinitions.map((column, index) => {
            return (
                <TableCell key={index} >
                    {createElement(column.component, props)}
                </TableCell>);
            })
        </TableRow>))