Home > Software design >  How to return incomplete jsx from map function
How to return incomplete jsx from map function

Time:11-26

I have data in an array of objects as below:

history = [
  {item: cake, calories: 120, datetime: 2022-11-16 07:51:26},
  {item: chicken, calories: 250, datetime: 2022-11-16 13:48:46},
  {item: pizza, calories: 420, datetime: 2022-11-25 11:13:42}
];

I want to render a div with a heading for the date and group all items with same dates in a list. I am using my map function like below:

function renderHistory () {
  let date;

  return props.history.map((item, i) => {
    const dateAdded = item.datetime.split(" ")[0];

    if (date !== dateAdded) {
      date = dateAdded;
      return (
        <>
          <div>
            <h2>{dateAdded}</h2>
            <li>{item.item} - {item.calories} calories</li>
        </>
      )
    }

    return (
      <>
          <li>{item.item} - {item.calories} calories</li>
        </div>
      </>
    )

  })
}

I get an error Expected corresponding JSX closing tag for <div>

If I return like below the second item gets out of the div.

return props.history.map((item, i) => {

  const dateAdded = item.datetime.split(" ")[0];

  if (date !== dateAdded) {
    date = dateAdded;
    return (
      <div>
        <h2>{dateAdded}</h2>
        <li>{item.item} - {item.calories} calories</li>
      </div>
    )
  }

  return (
    <li>{item.item} - {item.calories} calories</li>
  )

})

How do I put all items with same date in a single div?

CodePudding user response:

React under hood transforms JSX <div><h2>text</h2</div> into

React.createElement('div', undefined, React.createElement('h2',undefined,'text'))

what are you trying to do is impossible with this architecture.

Instead you need to find some other approach. Maybe group data by date and then render. Something like

function renderHistory () {
const grouped = props.history.reduce((acc,item)=>{
  const dateAdded = item.datetime.split(" ")[0];
   return {...acc, [dateAdded]: [...acc[dateAdded], item]}
  },{});

  return Object.keys(grouped).map((dayAdded) => {
     return (
     <div key={dayAdded}>
        <h2>{dateAdded}</h2>
       { grouped[dayAdded].map((item)=>(
         <li key={item.item dayAdded}>{item.item} - {item.calories} calories</li>)
         )}
      </div>
    )

  })
}

CodePudding user response:

import "./styles.css";
const foodItems = [
  { item: "cake", calories: 120, datetime: "2022-11-16 07:51:26" },
  { item: "chicken", calories: 250, datetime: "2022-11-16 13:48:46" },
  { item: "pizza", calories: 420, datetime: "2022-11-25 11:13:42" }
];

const foodItemsGroupedByDate = {};

foodItems.map((foodItem) => {
  const date = foodItem.datetime.split(" ")[0];
  foodItemsGroupedByDate[date] = foodItemsGroupedByDate[date] || [];
  foodItemsGroupedByDate[date].push({
    item: foodItem.item,
    calories: foodItem.calories
  });
});

const foodItemsArray = Object.entries(foodItemsGroupedByDate);

function RenderFoodItems({ items, date }) {
  return (
    <>
      <div>{date}</div>
      {items.map((item) => {
        return <div>{item.item} - {item.calories}</div>;
      })}
    </>
  );
}
export default function App() {
  return (
    <div className="App">
      {foodItemsArray.map((item) => {
        return <RenderFoodItems date={item[0]} items={item[1]} />;
      })}
    </div>
  );
}

Try something like this, tested in codesandbox.

CodePudding user response:

Add your if condition inside div tag..

  • Related