0

I'm building a tbody dynamically in reactjs. I have a function that creates seed data from a loop with this:

accounts.push(
  <tr key={i}>
  <td>{obj.type}</td>
  <td>{obj.name}</td>
  <td>{obj.balance}</td>
  <td>{obj.id}</td>
</tr>);

It works and i can populate rows in react with <tbody>{accounts}</tbody>. Now I'm trying to dynamically add <td>. I tried the following but it creates a string and ReactJS throws error Warning: validateDOMNesting(...): Text nodes cannot appear as a child of <tbody>:

let fields = ['type', 'name', 'balance', 'id'];

data.forEach( function(element, index) {
  let fieldsLabel = `<tr key=${++i}>`;
  fields.forEach( function(key, index) {
    fieldsLabel = fieldsLabel.concat(`<td>${element[key]}</td>`);
  });
  fieldsLabel = fieldsLabel.concat(`</tr>`);
  accounts.push(Array.from(fieldsLabel));
});

I'd like to do something simple like the following but it won't work because of the open <tr> tag:

    data.forEach( function(element, index) {
      let row = []
      row.push(<tr key={++i}>)
      fields.forEach( function(key, index) {
        row.push(<td>{element[key]}</td>)
      });
      row.push(</tr>)
      accounts.push(row.join(''));
    });

How do you dynamically push <td> into an array so it can be used in reactjs like {accounts}?

3 Answers 3

4

The following will dynamically add cells to table rows and dynamically create table rows for you to use in your components.

class TbodyRow extends React.Component {
  constructor() {
    super()
    this.createRow = this.createRow.bind(this);
  }

  createRow(tableRowID, data, dataOrder, cells = []) { 
    for (let i in dataOrder) {
      cells.push(<td key={i}>{data[dataOrder[i]]}</td>)
    }
    return (<tr key={tableRowID}>{cells}</tr>);
  }

  render() {
    return this.createRow(
      this.props.tbodyIdKey, 
      this.props.rowData, 
      this.props.dataOrder
    );
  }
}

Adding data cells (<td>) to a row (<tr>): Put this inside your method that's looping over your array of data (i.e [obj, obj, obj].forEach...):

let fields = ['type', 'name', 'balance', 'id'];
accounts.push(
  <TbodyRow key={obj.id}
    tbodyIdKey={obj.id} 
    rowData={obj} 
    dataOrder={fields}
  />
);

Then use in your tbody as requested:

<tbody>
  {accounts}
</tbody>
Sign up to request clarification or add additional context in comments.

Comments

1

try this

data.map((item,i) => {
  return(
    <tr key={++i}>
      {fields.length > 0 && fields.map((field,j) => {
         return(
            <td>{item[field]}</td>
         )
      })
    </tr>
  );
});

Comments

0

How do you dynamically push into an array so it can be used in reactjs like {accounts}?

You have the right idea but you're storing a string into fieldsLabel instead of a JSX element. Don't wrap your elements in backticks.

Don't use strings to create elements. Remember that JSX transpiles to React.createElement calls. If you create an element using strings then babel won't transpile that. Refer to the reactjs documentation to learn more about how JSX works.

Comments

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.