title: Render a calendar & appointments with React Hooks
body: <p>I am trying to create a calendar for each user that looks like that
  (ignore the styling it is not the final result) :</p>
  
  <p><a href="https://i.stack.imgur.com/WWFuT.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/WWFuT.png" alt="enter image description here"></a></p>
  
  <p>I have an array of appointments coming from the backend, I wanna render them where they should be based on the date and time.</p>
  
  <p>I can't find a good practice for that, I was thinking to use data attributes and change them after the appointments are loaded but the React website says to avoid it.
  So the only way I can think of is running on the appointments array every time I render a cell (I don't use table but div) and check if the time equals.
  I try to avoid it because it seems to me a bad practice, every rendered DIV will have to run on the appointments array and check if one of them matches by timestamp.</p>
  
  <p>Is there any way to render them after the calendar is rendered? like that I can change the specific cells and avoid unnecessary loops.</p>
  
  <p>I use React Hooks &amp; Redux for the frontend.</p>
  
  <p>Edit:
  Here is my code</p>
  
  <pre><code>import React, { useEffect, useState, useMemo } from 'react';
  import { useSelector } from 'react-redux';
  import moment from 'moment';
  
  function Calendar() {
      const calendarFromStore = useSelector(state =&gt; state.calendar);
      const [calendar, setCalendar] = useState({});
      const [settings, setSettings] = useState({
          currentWeek: [],
          diffWeeks: 0,
          totalAppointments: []
  }); 
  
  useEffect(() =&gt; {
      setCalendar(calendarFromStore);
      setSettings({ ...settings, currentWeek: getCurrentWeek })
  }, [calendarFromStore]);
  
  useEffect(() =&gt; {
      setSettings({ ...settings, currentWeek: getCurrentWeek })
  }, [settings.diffWeeks])
  
  const getCurrentWeek = useMemo(() =&gt; {
      let currentDate = moment().add(settings.diffWeeks, 'weeks');
      let days = [];
      for (let i = 3; i &gt;= 0; i--) {
          days.push(moment(currentDate).subtract(i, 'days').format('dddd DD/MM/YY'));
      }
      for (let i = 1; i &lt;= 3; i++) {
          days.push(moment(currentDate).add(i, 'days').format('dddd DD/MM/YY'));
      }
      return days;
  }, [settings.diffWeeks])
  
  const daysHeader = useMemo(() =&gt; {
      if (!settings.currentWeek) return;
      return settings.currentWeek.map((day, i) =&gt;
          &lt;div className={`day-title ${i === 3 &amp;&amp; !settings.diffWeeks ? 'today' : ''}`} key={day}&gt;
              &lt;span className="day"&gt;{day.substring(0, day.indexOf(' '))}&lt;/span&gt;
              &lt;span className="date"&gt;{day.substring(day.indexOf(' '))}&lt;/span&gt;
          &lt;/div&gt;)
  }, [settings.currentWeek, settings.diffWeeks]);
  
  const timeline = useMemo(() =&gt; {
      let currTime = '10:00';
      const stopTime = '19:00';
      const interval = 15;
      let timesArr = [];
      while (currTime !== stopTime) {
          timesArr.push(currTime);
          currTime = moment(currTime, 'HH:mm').add(interval, 'minute').format('HH:mm');
      }
      setSettings({ ...settings, totalAppointments: timesArr })
      return timesArr;
  }, [])
  
  const convertStringToTimestamp = (day, time) =&gt; {
      const fixedDay = day.substring(day.indexOf(' '));
      return moment(`${fixedDay} ${time}`, 'DD/MM/YY HH:mm').unix();
  }
  
  const calendarApts = useMemo(() =&gt; {
      if (!settings.currentWeek) return;
      return settings.currentWeek.map(day =&gt;
          &lt;div className="line" key={day}&gt;
              {timeline.map(time =&gt;
                  &lt;div key={`${day} ${time}`}
                      time={convertStringToTimestamp(day, time)} onClick={() =&gt; console.log(day, time)}&gt;
                  &lt;/div&gt;)
              }
          &lt;/div&gt;
      )
  }, [settings.currentWeek, timeline])
  
  useMemo(() =&gt; {
      calendar.appointments &amp;&amp; calendar.appointments.map(apt =&gt; apt);
  }, [calendar.appointments])
  
  const changeWeeks = val =&gt; {
      setSettings({ ...settings, diffWeeks: !val ? 0 : settings.diffWeeks + val })
  }
  
  return (
      &lt;div className="calendar-container"&gt;
          &lt;div className="navigation"&gt;
              &lt;div className="last-buttons"&gt;
                  &lt;button onClick={() =&gt; changeWeeks(-5)}&gt;Last month&lt;/button&gt;
                  &lt;button onClick={() =&gt; changeWeeks(-1)}&gt;Last week&lt;/button&gt;
              &lt;/div&gt;
              &lt;button onClick={() =&gt; changeWeeks(0)}&gt;Current Week&lt;/button&gt;
              &lt;div className="next-buttons"&gt;
                  &lt;button onClick={() =&gt; changeWeeks(1)}&gt;Next week&lt;/button&gt;
                  &lt;button onClick={() =&gt; changeWeeks(5)}&gt;Next month&lt;/button&gt;
              &lt;/div&gt;
          &lt;/div&gt;
          &lt;div className="calendar-header"&gt;
              {daysHeader}
          &lt;/div&gt;
          &lt;div className="calendar-content"&gt;
              &lt;div className="calendar-timeline"&gt;
                  {timeline.map(time =&gt; &lt;div key={time}&gt;&lt;span&gt;{time}&lt;/span&gt;&lt;/div&gt;)}
              &lt;/div&gt;
              &lt;div className="calendar-vertical-lines"&gt;
                  {calendarApts}
              &lt;/div&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  )
  }
  
  export default Calendar;
  </code></pre>