I have a component called Cells which renders with data that is gotten from a flux store. My problem is that I want to render this data to a specific row but because of the way I am rendering the rows (they are dynamic so you can add them to the table), I am struggling to give the rows identifiers which the cell component can render into. I hope that makes sense!
Here is the code:
Cells Component:
import React from 'react';
export default class Cells extends React.Component {
render() {
return (
<td>{this.props.value}</td>
);
}
}
Table Component:
import React from 'react';
import TableHeader from './TableHeader.jsx';
import Cells from './Cells.jsx';
import RowForm from './RowForm.jsx';
import {createRow} from '../../actions/DALIActions';
import AppStore from '../../stores/AppStore';
export default class Table extends React.Component {
state = {rows: [], cellValues: [], isNew: false, isEditing: false};
updateState = () => this.setState({cellValues: AppStore.getCellValues()});
componentWillMount() {
AppStore.addChangeListener(this.updateState);
}
handleAddRowClickEvent = () => {
let rows = this.state.rows;
rows.push({isNew: true});
this.setState({rows: rows});
};
handleEdit = (row) => {
this.setState({isEditing: true});
};
editStop = () => {
this.setState({isEditing: false});
};
handleSubmit = (access_token, id, dataEntriesArray) => {
createRow(access_token, id, dataEntriesArray);
};
componentWillUnmount() {
AppStore.removeChangeListener(this.updateState);
}
render() {
let {rows, cellValues, isNew, isEditing} = this.state;
let headerArray = AppStore.getTable().columns;
let cells = this.state.cellValues.map((value, index) => {
return (
<Cells key={index} value={value.contents} />
);
});
return (
<div>
<div className="row" id="table-row">
<table className="table table-striped">
<thead>
<TableHeader />
</thead>
<tbody>
//////////// This is where the render of the data would happen/////////////
{rows.map((row, index) => this.state.isEditing ?
<RowForm formKey={index} key={index} editStop={this.editStop} handleSubmit={this.handleSubmit} /> :
<tr key={index}>
{this.state.cellValues ? cells : null}
<td>
<button className="btn btn-primary" onClick={this.handleEdit.bind(this, row)}><i className="fa fa-pencil"></i>Edit</button>
</td>
</tr>
)}
///////////////End/////////////////
</tbody>
</table>
</div>
<div className="row">
<div className="col-xs-12 de-button">
<button type="button" className="btn btn-success" onClick={this.handleAddRowClickEvent}>Add Row</button>
</div>
</div>
</div>
);
}
}
I know this isn't probably the best way to achieve what I want (any tips on that would be appreciated as well), but its what I have to work with at the moment!
Any help would be much appreciated, especially examples!
Thanks for you time!
Instead of having one object (rows) that contains row headers, and another object that contains all cells for all rows (cellvalues), I would advise you to put the cell data inside the individual row data in some way, so that your data structure would look something like this:
rows = [
{ rowID: 100, cells: [
{ cellID: 101, value: 'data' },
{ cellID: 102, value: 'data' }
]
},
{ rowID: 200, cells: [
{ cellID: 201, value: 'data' },
{ cellID: 202, value: 'data' }
]
}
]
That way, you pass the cellValues per row, and that allows you to have different cells per row.
Make a separate component for <Row>, which renders:
return
<tr>
{this.props.cells.map( cell => {
return <Cell key={cell.cellID} value={cell.value} />
})}
</tr>
And change the <tr> bit inside your main render to:
<Row key={row.keyID} cells={row.cells}/>
Finally: it is a bad idea to use the index for keys, as in key={i}. Use a key that uniquely identifies the content of the cell/ row.
UPDATE: A typical situation is that cells or rows are first created in front-end, and only get their database ID after posting to database.
Options to still get unique IDs for the keys are:
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With