Reputation: 4461
ERROR:
main.js:1583 Uncaught Error: Objects are not valid as a React child (found: [object HTMLTableElement]). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons.
CODE:
var size = 40
var Board = createReactClass ({
getInitialState() {
var array = [];
var cellsArray = [];
for (var i = 0; i < size; i ++) {
array.push(cellsArray);
for (var j = 0; j > size; j++) {
array[i].push(<Cell start={this.props.start}/>);
}
}
return {
array: array
};
},
render() {
var i = 0;
var tableData = this.state.array.map(rowData => {
i++
return (
<tr key={i}>
{
rowData.map(cellData => {
return ({cellData});
})
}
</tr>
);
})
return (
<table>
<tbody>
{tableData}
</tbody>
</table>
);
}
})
var Cell = createReactClass ({
getInitialState() {
return {
selected : false,
}
},
handleClick() {
this.setState({
selected: !this.state.selected
})
},
render() {
return <td onClick = {this.handleClick} className={this.state.selected ? "cell selected" : "cell"}></td>;
}
})
QUESTION:
I would like to render the programmatically created table. How can I do that ?
UPDATE:
CSS:
.cell {
width: 1em;
height: 1em;
border: 1px solid #ddd;
}
.selected {
background-color: black;
}
table {
border: 1px solid black;
border-collapse: collapse;
margin: auto;
margin-bottom: 50px;
}
Upvotes: 1
Views: 1361
Reputation: 9408
You need to create it React
way. Your createTable
method should look something like below.
createTable(tableData) {
return (
<table>
<tbody>
{
tableData.map(rowData => {
return (<tr key={rowData.Id}>
{
rowData.map(cellData => {
return (<td key={cellData}> {cellData} </td>);
})
}
</tr>);
})
}
</tbody>
</table>
)
Note: You need to put in a unique key for the root of jsx inside the 'maps'. Identify the unique key for each iteration. As a last resort you can use index
, but that is not recommended.
EDIT: Updated for new changes
In your updated code, the td
is empty and hence its displayed empty on the page.
Other changes you would require
Your initial state should not generate an JSX. It should be used only to compute the initial state and return a plain object. You are returning a object that contains array of JSX elements in it, which fundamentally defeats the purpose of React that it needs to require the DOM to be dynamically updated appropriately based on prop
/state
changes. Your initialState
should only contain the data that is required to construct the needed DOM elements.
getInitialState() {
var array = [];
var cellsArray = [];
for (var i = 0; i < size; i ++) {
array.push(cellsArray);
for (var j = 0; j > size; j++) {
array[i].push(/* push data that you need to construct your cell */);
}
}
return {
array: array
};
}
Then in your tableData
function , you need to form the required JSX. This function is getting called inside of render
which is perfectly fine place to produce the DOM elements.
var tableData = this.state.array.map(rowData => {
i++
return (
<tr key={i}>
{
rowData.map(cellData => {
return <Cell key={cellData} data={cellData} start={this.props.start} />
})
}
</tr>
);
})
Finally in your Cell
, render
method you need to pass some children for td
for it to be visible on the screen. In you question its empty and so the image you have posted showing the DOM elements and it being empty is the right behaviour. You need to do something like below
render() {
return (<td onClick = {this.handleClick} className={this.state.selected ? "cell selected" : "cell"}>
{this.props.data }
{ /* or whatever data you want to be put here */ }
</td>);
}
Upvotes: 3