Reputation: 323
How to pass a relative component through props to another component to render it?
For example pass to component table from app.js a props with a component button with relative calls and just call it like in code bellow? Is it possible?
Error
Element type is invalid: expected a string (for built-in components) or a >class/function (for composite components) but got: object.
In the Table.js component
import React from "react";
import { Container } from "./styles";
const Table = ({ data, columns }) => {
return (
<Container>
<thead>
<tr>
{columns.map((header) => {
return <th>{header.text}</th>;
})}
</tr>
</thead>
<tbody>
{data.map((dado) => {
return (
<tr>
{columns.map((column) => {
var { Mask } = column;
console.log(Mask);
return (
<td>
<Mask />
</td>
);
})}
</tr>
);
})}
</tbody>
</Container>
);
};
export default Table;
App.js
import React from "react";
import "./styles.css";
import Table from "./Table";
export default function App() {
const data = [
{ name: "teste", age: 30, place: "brazil", place2: "brazil" },
{ name: "teste", age: 30, place: "brazil", place2: "brazil" },
{ name: "teste", age: 30, place: "brazil", place2: "brazil" }
];
const columns = [
{
dataField: "name",
text: "Nome",
Mask: (
<button
type="button"
onClick={() => {
console.log("Do Something");
}}
>
{data.name}
</button>
)
},
{
dataField: "age",
text: "Idade",
Mask: (
<button
type="button"
onClick={() => {
console.log("Do Something");
}}
>
{data.name}
</button>
)
},
{
dataField: "place",
text: "Localidade",
Mask: (
<button
type="button"
onClick={() => {
console.log("Do Something");
}}
>
{data.name}
</button>
)
},
{
dataField: "place2",
text: "2",
Mask: (
<button
type="button"
onClick={() => {
console.log("Do Something");
}}
>
{data.name}
</button>
)
}
];
return (
<div className="App">
<Table data={data} columns={columns} />
</div>
);
}
Upvotes: 1
Views: 651
Reputation: 156
<Mask />
is applicable to function or class components only, so Mask
should be either a function or a class. In the example above it is a React element, not a React component.
Please, take a look at this article to understand the difference.
So in order to render it, it is just necessary to use it as a value, like this:
{columns.map((column) => {
var { Mask } = column;
console.log(Mask);
return (
<td>
{Mask}
</td>
);
})}
UPDATE: I didn't fully understand the question at first. So in order to pass data to Mask
, you can use an approach from another answer or turn it into a function like this:
const columns = [
{
dataField: "name",
text: "Nome",
Mask: ({ children }) => (
<button
type="button"
onClick={() => {
console.log("Do Something");
}}
>
{children}
</button>
)
},
...
];
and render it as you did in your question:
{data.map((dado) => {
return (
<tr>
{columns.map((column) => {
var { Mask, dataField } = column;
console.log(Mask);
return (
<td>
<Mask>
{dado[dataField]}
</Mask>
</td>
);
})}
</tr>
);
})}
Upvotes: 1
Reputation: 10651
Make following changes to Table.js
:
import React from "react";
// import { Container } from "./styles";
const Table = ({ data, columns }) => {
return (
<>
<thead>
<tr>
{columns.map(header => {
return <th>{header.text}</th>;
})}
</tr>
</thead>
<tbody>
{data.map(dado => {
return (
<tr>
{columns.map((column, index) => {
let { Mask } = column;
console.log(column["Mask"]);
Mask = {
...Mask,
props: { children: dado[Object.keys(dado)[index]] }
};
/*------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^
above you can see how we can set the children props of button
*/
return <td>{Mask}</td>;
})}
</tr>
);
})}
</tbody>
</>
);
};
export default Table;
Full working example: Stackblitz
Upvotes: 1