0

Currently I am struggling with iterating over an object containing an array with objects. (and nested ones) I am trying to create a generic Table Component in React so it can be used by many views.

What did I setup?

tableData.map((prop, key) => {
  return (
    <TableRow key={key}>
      <TableCell className={classes.tableCell} key={key}>
        {prop.number}
      </TableCell>
      <TableCell className={classes.tableCell} key={key}>
        {prop.TableType.max_occupancy}
      </TableCell>
      <TableCell className={classes.tableCell} key={key}>
        {prop.price}
      </TableCell>
      <TableCell className={classes.tableCell} key={key}>
        {prop.TableType.description}
      </TableCell>
      <TableCell className={classes.tableCell} key={key}>
        <Button fullWidth color="primary">
          Remove
        </Button>
      </TableCell>
    </TableRow>
  );
})

The problem that I am facing right now?

I can not create the content above in a dynamic way. I am encountering several issues like for example:

  • The nested objects logic
  • The logic should not clash with other implementations in other pages. (react)

What would I like to achieve?

I would like to achieve something that is generic and can be used in a wide range of scenarios and does not clash with other pages where this component is being used.

In the end it should look something like this in a visual way:

enter image description here

What data do I have?

[
    {
        "id": 1,
        "number": 1,
        "status": true,
        "price": 12,
        "table_type_id": 1,
        "venue_id": 1,
        "TableType": {
            "id": 1,
            "description": "Small Table",
            "max_occupancy": 3
        }
    },
    {
        "id": 2,
        "number": 2,
        "status": true,
        "price": 2,
        "table_type_id": 2,
        "venue_id": 1,
        "TableType": {
            "id": 2,
            "description": "Medium Table",
            "max_occupancy": 6
        }
    }
]

The Codesandbox directory with the full project: https://codesandbox.io/embed/lwzz4j9mz?autoresize=1&eslint=1 The fill we are talking about is located at the Components/Table/Table.jsx. (I have added some dummy data in the comments that needs to be parsed to Table rows and cells)

Properties that needs be used in the view:

  • number
  • price
  • id
  • TableType

Hopefully someone can come up with a smart idea to help me out with this issue! Cheers for all the help and hopefully we can fix this together.

14
  • 1
    I think it's a good idea to add what you tried as a codesandbox.io link Commented May 2, 2018 at 9:10
  • 1
    What should be the behaviour when there is nested logic? Is it guaranteed that the nested properties will always be objects or could they be something else for eg arrays? Commented May 2, 2018 at 9:14
  • 2
    As a general point, don't give every component in a list the same key. The purpose of the key property for component lists is to help React differentiate them. That's not gonna work if they're all the same. Specifically, what issues are you facing? You say The nested objects logic, what logic? They're just simple key pair objects, so what logic do you mean, accessing their values? Also you said The logic should not clash with other implementations, that's gonna be REAL hard for us to help with when we don't have any context of the rest of the app Commented May 2, 2018 at 9:17
  • 1
    I'd use a third party like react-table github.com/react-tools/react-table Commented May 2, 2018 at 9:30
  • 1
    Is your request to make it more DRY and for a way for the parent of table to specify how to access each data in each cell rather than hard coding it? Commented May 2, 2018 at 10:03

1 Answer 1

1

You should probably use an external library to get this done. But if you want to go for an in house approach this would be one way to go about it.

To the component, send the data and the header.The header should also specify how the data should be parsed to receive it's value.

var defaultTemaplate = '<TableRow><TableCell style={{ textAlign: "center" }}>Woooops! You haven\'t applied any tables for this venue yet. To start renting out tables you should add at least 3 tables tothe app. Just press the button above to start imediately.</TableCell></TableRow>'
var tableHead = [{
    title: 'number',
    type: 'data',
    path: 'number'
  },
  {
    title: 'TableType',
    type: 'data',
    path: 'TableType.description'
  },
  {
    title: 'Edit/delete',
    type: 'template',
    templateString: '<button></button>'
  }
] //for all columns
var tableData = [{
    "id": 1,
    "number": 1,
    "status": true,
    "price": 12,
    "table_type_id": 1,
    "venue_id": 1,
    "TableType": {
      "id": 1,
      "description": "Small Table",
      "max_occupancy": 3
    }
  },
  {
    "id": 2,
    "number": 2,
    "status": true,
    "price": 2,
    "table_type_id": 2,
    "venue_id": 1,
    "TableType": {
      "id": 2,
      "description": "Medium Table",
      "max_occupancy": 6
    }
  }
]
console.log(genRows(tableData))

function getTableCells(data) {
  return tableHead.map((opts) => {
    if (opts.type === 'data') {
      return `<TableCell className={classes.tableCell}>${_.at(data, opts.path)}</TableCell>`
    }
    if (opts.type === 'template') {
      return opts.templateString
    }
  })
}

function genRows(tableData) {
  if (tableData.length < 0) return defaultTemaplate;
  return tableData.map((rowData) => `<TableRow>${getTableCells(rowData)}</TableRow>`)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.js"></script>

This is just an example to demonstrate one approach you could take, not full fledged code and can defenetly be improved.

Sign up to request clarification or add additional context in comments.

11 Comments

It thrown an error undefined for the path property when an array is given.
That was not a fully tested code. it was just a minimal code to show an approach you could take let me correct it.
Ahhh I see, sorry about that! Would you mind to have a look over it? This is giving me a very good direction but I am still stuck. I'll accept the answer then! :) Thanks a lot in advance sir
It was classic messup of === with = :P. Ive corrected it now. Adapting it to react is upto you ;)
You can replace it with lodash at or ramda's paths if use any of those libs
|

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.