Правильный способ использования useEffect для обновления дочернего компонента после замены массива состояний - PullRequest
0 голосов
/ 26 октября 2019

У меня есть родительский компонент «Оформить заказ», где я вызываю свой API для билетов на мероприятия и сохраняю данные в состояние. У меня есть простая функция, которая берет существующую информацию о билете и добавляет ее к заявке, выбранной пользователем.

Компонент извлечения

    const handleTicketAdd = (e) => {
    // create new ticket array
    const newTickets = tickets;
    // 
    newTickets[e.target.id].count++;
    console.log(newTickets);
    setTickets(newTickets);
    console.log(tickets);
  }

Эта функция передается в качестве опоры дочернему компоненту «Билеты» и вызывается в сопоставленной строке.

Функция работает нормально и обновляет состояние счета в консоли, но дочерний компонент не выполняет повторную визуализацию, а значения на экране остаются с начальным значением.

Я былисследования и обнаружили, что componentWillReceiveProps был заменен хуком useEffect. Я пытался заставить его работать в моем дочернем компоненте без успехов:

Тикет Компонент

useEffect(()=>{
    console.log("Tickets Changed", props.tickets);
}, [props.tickets]);

Журнал не запускается при изменении props.tickets, поэтому я знаю, что я не обращаюсь с этим правильно. Может кто-нибудь направить меня в правильном направлении.

Обновление

На основании приведенной ниже обратной связи я пересмотрел свой код, и он почти завершен. Проблема в том, что он добавляет новое поле массив со значением счетчика объекта, а не просто обновляет поле счетчика объекта.

setTickets(prevTickets => ([...prevTickets, prevTickets[e.target.id].count = prevTickets[e.target.id].count + 1])
  )

Если я попробую что-то наподобие всплытия последнего значения, я получу еще больше новых полей, добавленных в массив. Как бы я добился удаления дополнительного поля, которое создается. Не работает следующее:

    setTickets(prevTickets => ([...prevTickets, prevTickets[e.target.id].count = prevTickets[e.target.id].count + 1], prevTickets.pop()),
  )


    setTickets(prevTickets => ([...prevTickets, prevTickets[e.target.id].count = prevTickets[e.target.id].count + 1], prevTickets.slice(-1)[0),
  )

Ответы [ 2 ]

1 голос
/ 26 октября 2019

Вы не должны изменять состояние при обновлении, вместо этого вам нужно клонировать и обновить состояние

const handleTicketAdd = (e) => {
    const id = e.target.id;
    setTickets(prevTickets => ([
         ...prevTickets.slice(0, id),
         {
             ...prevTickets[id],
             count: prevTickets[id].count + 1
          }
         ...prevTickets.slice(id + 1);
    ]));
  }
0 голосов
/ 26 октября 2019

Хорошо, похоже, способ редактирования массива в состоянии должен выполняться с помощью функции карты или цикла с использованием предыдущего состояния. Я смог решить это, основываясь на отзывах Шубхэма.

// update count based on previous state 
  setTickets(prevTickets => (prevTickets.map((ticket, index) => {
    console.log(index, e.target.id);
    // if mapped object's id equals the arrays index, it's the value to edit
    if (e.target.id == index) {
      console.log(index);
      const count = ticket.count + 1;
      // return object with updated count values
      return { ...ticket, count }
    }
    return ticket;
  })
  ))

Это дает мне возможность редактировать значение объекта, которое я хочу в моем массиве, без каких-либо дополнительных полей или значений.

...