React - Условия в Map отрабатывают не так, как я ожидал

С бэка мне приходит массив объектов в таком виде:

0: {_id: '6149ed683444e100fa6830b5', user: '61487ece544179033653eac5', date: '2021-09-03T00:00:00.000Z', time: '2', __v: 0}
1: {_id: '614ad40b9643c003b3222ef3', user: '61487ece544179033653eac5', date: '2021-09-07T00:00:00.000Z', time: '3', __v: 0}
2: {_id: '614ae776890fa8046b12ead9', user: '61487ece544179033653eac5', date: '2021-09-04T00:00:00.000Z', time: '2', __v: 0}
3: {_id: '614aeb79890fa8046b12eb7b', user: '61487ece544179033653eac5', date: '2021-09-13T00:00:00.000Z', time: '1', __v: 0}
4: {_id: '614aefbe890fa8046b12ec01', user: '61487ece544179033653eac5', date: '2021-09-05T00:00:00.000Z', time: '4', __v: 0}
5: {_id: '614b195fc80ddd0b8b230d8b', user: '61487ece544179033653eac5', date: '2021-09-23T00:00:00.000Z', time: '3', __v: 0}
6: {_id: '614b52ed1b973001155b6380', user: '61487ece544179033653eac5', date: '2021-09-08T00:00:00.000Z', time: '3', __v: 0}
7: {_id: '614b53311b973001155b63a5', user: '61487ece544179033653eac5', date: '2021-09-09T00:00:00.000Z', time: '3', __v: 0}

Я пробегаюсь по этом массиву объектов таким образом с помощью map:

{store.time.map((time, indx) => (

   <>
      {time.time && time.date === dayOfMonth ? (
        <div className="flex items-center edit h-10 bg-custom-orange justify-center text-white rounded-sm">
          <div className="text-2xl">{time.time} ч.</div>
          <div className="ml-3 cursor-pointer hover:opacity-90">
            <svg
              width="15"
              height="15"
              viewBox="0 0 19 19"
              fill="none"
              xmlns="http://www.w3.org/2000/svg">
              <path
                d="M2.375 13.6562V16.625H5.34375L14.0996 7.86916L11.1308 4.90041L2.375 13.6562ZM16.3954 5.57333C16.7042 5.26458 16.7042 4.76583 16.3954 4.45708L14.5429 2.60458C14.2342 2.29583 13.7354 2.29583 13.4267 2.60458L11.9779 4.05333L14.9467 7.02208L16.3954 5.57333Z"
                fill="#fff"
              />
            </svg>
          </div>
        </div>
      ) : (
        <div className="flex">
          <input
            type="text"
            onChange={(e) => onChange(e)}
            className="flex items-center justify-center w-10 h-10 rounded-md mr-2 max-w-10 max-h-10 text-md time-input"
          />

          <div onClick={() => sendTime(user._id)} className="cursor-pointer hover:opacity-90">
            <svg
              width="40"
              height="40"
              viewBox="0 0 60 60"
              fill="none"
              xmlns="http://www.w3.org/2000/svg">
              <path
                d="M53.3333 0H6.66667C2.96667 0 0 3 0 6.66667V53.3333C0 57 2.96667 60 6.66667 60H53.3333C57 60 60 57 60 53.3333V6.66667C60 3 57 0 53.3333 0ZM46.6667 33.3333H33.3333V46.6667H26.6667V33.3333H13.3333V26.6667H26.6667V13.3333H33.3333V26.6667H46.6667V33.3333Z"
                fill="#86C443"
              />
            </svg>
          </div>
        </div>
      )}
    </>
))}

Условие звучит так:

  • если в этом объекте есть время и дата этого объекта совпадает с датой в таблице -> отобрази мне этот элемент заполненным, если нет -> отобрази пустой инпут. Но проблема в том, что сравнивается каждый объект в массиве с каждой датой из таблицы, и на выходе я получаю следующее: введите сюда описание изображения

Ожидаю же я увидеть такой результат: введите сюда описание изображения

Таблица чисел месяца формируется отдельно от таблицы с датами. На сервере это выглядит так:

async generateDate() {
    const value = moment();
    const startDay = value.clone().startOf("month").startOf("week");
    const endDay = value.clone().endOf("month").endOf("week");
    const day = startDay.clone().subtract(-4, "day");
    const calendar = [];

    while (day.isBefore(endDay, "day")) {
      calendar.push(
        Array(1)
          .fill(0)
          .map(() => day.add(1, "day").clone()),
      );
    }

    return calendar;
  }

На клиенте так:

{store.calendar.map((week: any) => (
  <li className="mr-4">
    {week.map((day: any) => (
      <div className="flex">
        <div className="text-2xl w-10 h-10 p-4 flex items-center justify-center">
                {moment(day).format("D").toString()}
         </div>
                      
      </div>
))}
</li>

В голову приходят только костыльные решения с display none. Но мне почему-то кажется есть более правильный способ решить эту проблему. Заранее благодарен за помощь в этом вопросе!


Ответы (2 шт):

Автор решения: Radik

Когда мы проходим map в Reacte мы всегда должны указывать key для элементов. Я не уверен что это до конца решит проблему. Ключи помогают React определять, какие элементы были изменены, добавлены или удалены. Их необходимо указывать, чтобы React мог сопоставлять элементы массива с течением времени:

const numbers = [1, 2, 3, 4, 5]; const listItems = numbers.map((number) => {number} );

→ Ссылка
Автор решения: Евгений Николаев

const data = [
  {
    "_id": "614ed395ae139cd283c04b77",
    "user": "05213607-0456-48af-b611-5758ef62098d",
    "date": "2021-09-26",
    "time": 0
  },
  {
    "_id": "614ed395b026737708dbf328",
    "user": "de9f26a6-ee0a-42d0-8d84-7b93073330fc",
    "date": "2021-09-29",
    "time": 2
  },
  {
    "_id": "614ed395deca8f0b84f63a33",
    "user": "ca5017e3-85e5-412b-a468-59cd0bca960b",
    "date": "2021-09-30",
    "time": 2
  },
  {
    "_id": "614ed395dae3c5efde6f9721",
    "user": "f68459ca-27c6-4f4e-9334-8845f82012a8",
    "date": "2021-09-28",
    "time": 6
  },
  {
    "_id": "614ed3950a0b5db824a537f2",
    "user": "7840b774-e604-4d9b-8f8b-da7ce782ecab",
    "date": "2021-09-26",
    "time": 2
  },
  {
    "_id": "614ed395b4bba2149ec12f78",
    "user": "6a5895d4-2649-4e5f-936f-05e6ec7a0a42",
    "date": "2021-09-30",
    "time": 6
  }
];

const date = [];
// сформируем массив дат
for (let i = 1; i <= 30; i++){
  date.push({
    date: `2021-09-${i}`
  });
}

//объединили два массива по датам.
date.map((value) => {
  const find = data.filter(item => value.date == item.date);
  value.list = find;
});

console.log(date);

Из примера видно, что мы получаем один массив со всеми необходимыми данными, которые объединены по дате. Соответственно, теперь куда легче сделать вывод этой информации. Если у нас в объекте массив list пустой, то отрисовывай плюс (добавление). Если у нас массив list имеет значения, то отрисовываем их.

→ Ссылка