Home > Back-end >  Internal Iteration on Array.map so the value is displayed once while it is not changed
Internal Iteration on Array.map so the value is displayed once while it is not changed

Time:07-08

I'm building a simple News display, where the date is displayed on a Typography element and below of this Typography each Novedad is a new. I'm trying to iterate so the date is got from the first news (the news are already ordered by date DESC). so, while other news have the same date, no new title box with the date should appear.

However I don't know how to approach this programming. Notice I'm using React and I'm trying to use conditional rendering.

In short, I'm trying to display an array of objects grouping them by date with another element showing this date.

The following code displays each news with a date title above, which is not the intented result.

novedades.map((novedad)=>{
        return(
        <>  
            <Typography variant="h6" component="div">
                {moment(novedad.date).format("dddd, DD/MM/YYYY")}
            </Typography>

            /*The following element should be iterated so while novedad.date does not change it does not exit the loop*/
            <Novedad key={novedad.id} tipo={novedad.tipo} creador={novedad.creado_por} fecha={novedad.date} contenido={novedad.contenido_html}/>
        </>
)})

CodePudding user response:

You can try grouping the news by date before rendering them. A simple solution will be to use a simple key-value pair approach like the one bellow

const [groupedNewsByDate, setGroupedNewsByDate] = useState(null);

useEffect(() => {
  // fake HTTP request
  Promise.resolve([
  {
    date: "2022-07-07T14:50:10.489Z",
    id: 4,
    content: "News 4"
  },
  {
    date: "2022-07-07T14:50:10.489Z",
    id: 3,
    content: "News 3"
  },
  {
    date: "2022-07-06T14:50:10.489Z",
    id: 2,
    content: "News 2"
  },
  {
    date: "2022-07-05T14:50:10.489Z",
    id: 1,
    content: "News 1"
  }
]).then((entries) => {
  // grouping news that have the same date
  setGroupedNewsByDate(
    entries.reduce((map, item) => {
      const items = map[item.date] || [];
      items.push(item);
      map[item.date] = items;
      return map;
    }, {})
  );
});
}, []);

function renderNews() {
  const dates = Object.keys(groupedNewsByDate);
  // render fallback ui if no news
  if (dates.length === 0) {
    return <span>No news</span>;
  }

// render news grouped by date
return dates.map((date) => (
  <section key={date} aria-labelledby={date}>
    <h2 id={date}>{new Date(date).toLocaleDateString()}</h2>
    {groupedNewsByDate[date].map((item) => (
      <div key={item.id}>{item.content}</div>
    ))}
  </section>
));
}

Live demo: https://codesandbox.io/s/reverent-pare-5m9mme?file=/src/App.js

CodePudding user response:

This is one way you could do this:

const dates=array.map(novedad=>novedad.date)
const uniqueDates=[... new Set(dates)]

... rest of code ...

{uniqueDates.map(date=>{
return (
  <Typography variant="h6" component="div">
                {moment(date).format("dddd, DD/MM/YYYY")}
  </Typography>

{novedades.map(novedad=>{
 return novedad.date==date&&<Novedad key={novedad.id} tipo={novedad.tipo} creador={novedad.creado_por} fecha={novedad.date} contenido={novedad.contenido_html}/>
})})}
  • Related