0

I'm writing a code in react, where in I want to display the json data in HTML table. I want this to be dynamic. i.e. irrespective of the type of json data I'm using, it should render in tabular format.

Here is my code with sample data.

const jsArray =  [{"Model":"Mazda RX4","mpg":21,"cyl":6},{"Model":"Mazda RX4 Wag","mpg":21,"cyl":6},{"Model":"Datsun 710","mpg":22.8,"cyl":""},{"Model":"Hornet 4 Drive","mpg":21.4,"cyl":""},{"Model":"Hornet Sportabout","mpg":18.7,"cyl":8},{"Model":"Valiant","mpg":18.1,"cyl":6}];

 {jsArray.length > 0 && (
        <table>
          <thead>
            {jsArray.map((item, idx) =>
              idx === 0 ? (
                <th key={idx}>
                  {Object.values(item).forEach((val) => (
                    <td>{val}</td>
                  ))}
                </th>
              ) : (
                <tr key={idx}>
                  {Object.values(item).forEach((val) => (
                    <td>{val}</td>
                  ))}
                </tr>
              )
            )}
          </thead>
        </table>
      )}

When I run this code, nothing is getting rendered. When I replace <tr key={idx}>{Object.values(item).forEach((val)=> (<td>{val}</td>))}</tr> with null, In my output I see null printed in my front end. Please let me know where I'm going wrong.

5
  • jsArray is a string, not an array. You can't map over it. Commented Apr 12, 2022 at 12:32
  • use JSON.parse(jsArray).map() because jsArray is a stinrg Commented Apr 12, 2022 at 12:34
  • My bad @Andy and @Liki. The` jsArray` I added here is sample data. In my real code, it is of type object. Updated the code in my question; Commented Apr 12, 2022 at 12:40
  • Do note that while adding key={idx} does get rid of the warning, it is not correct. key is used to detect order change; using order index defeats the purpose. Commented Apr 12, 2022 at 12:50
  • I didn't catch you @ColouredPanda. Sorry, I'm learning react and trying out different things to get an hands on. Commented Apr 12, 2022 at 12:53

2 Answers 2

3

It might make it easier if you broke all that logic down into more helpful functions.

  1. getHeadings maps over the first object and grabs its keys.

  2. getRows maps over all the data, and calls getCells with each object's data.

  3. getCells maps over the object and uses Object.values to get the information for each cell.

This way your component is a lot cleaner.

// `map` over the first object in the array
// and get an array of keys and add them
// to TH elements
function getHeadings(data) {
  return Object.keys(data[0]).map(key => {
    return <th>{key}</th>;
  });
}

// `map` over the data to return
// row data, passing in each mapped object
// to `getCells`
function getRows(data) {
  return data.map(obj => {
    return <tr>{getCells(obj)}</tr>;
  });
}

// Return an array of cell data using the
// values of each object
function getCells(obj) {
  return Object.values(obj).map(value => {
    return <td>{value}</td>;
  });
}

// Simple component that gets the
// headers and then the rows
function Example({ data }) {
  return (
    <table>
      <thead>{getHeadings(data)}</thead>
      <tbody>{getRows(data)}</tbody>
    </table>
  );
}

const data = [{"Model":"Mazda RX4","mpg":21,"cyl":6},{"Model":"Mazda RX4 Wag","mpg":21,"cyl":6},{"Model":"Datsun 710","mpg":22.8,"cyl":""},{"Model":"Hornet 4 Drive","mpg":21.4,"cyl":""},{"Model":"Hornet Sportabout","mpg":18.7,"cyl":8},{"Model":"Valiant","mpg":18.1,"cyl":6}];

ReactDOM.render(
  <Example data={data} />,
  document.getElementById('react')
);
table { border: 1px solid #dfdfdf; border-collapse: collapse; }
th { background-color: #efefef; text-align: left; text-transform: uppercase; }
td { border: 1px solid #efefef; }
td, th { padding: 0.4em; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

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

Comments

2

You can do it like this:

  const data = JSON.parse(jsArray);
  const keys = Object.keys(data.length ? data[0] : {});
  return (
    <div className="App">
      {jsArray.length > 0 && (
        <table>
         <thead>
            <tr>
              {keys.map((item, idx) => (
                <th key={idx}>{item}</th>
              ))}
            </tr>
          </thead>
          <tbody>
            {data.map((item, idx) => (
              <tr key={idx}>
                {keys.map((key, idx) => (
                  <td>{item[key]}</td>
                ))}
              </tr>
            ))}
          </tbody>
        </table>
      )}
    </div>
  );

1 Comment

This is the way to go, small nit tho you should remove the idx param in the last map (duplicate and unused declaration)

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.