@livd98

Почему не перерисовывается компонент при изменении стейта?

Вывожу список из кубиков, хочу менять их местами перетягивая друг на друга через drag, всё работает, но только в консоль логе, сам же список кубиков не перерисовывается, хоть я и меняю стейт списка. Проблема где то в dragDropHandler. На typescript внимания не обращайте
6352ba897f220219214914.jpeg
import React, {useState} from 'react'
import './App.css'

interface ICurrentCard {
  currentCard: any;
}

export const App = () => {
  const [cardList, setCardList] = useState([
    {id: 1, text:' card number 1'},
    {id: 2, text:' card number 2'},
    {id: 3, text:' card number 3'},
    {id: 4, text:' card number 4'},
  ])
  const [currentCard, setCurrentCard] = useState<ICurrentCard | any> (null)

  const dragOverHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
    e.preventDefault()
    e.target.style.background = 'lightgray'
  }

  const dragLeaveHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
    e.target.style.background = 'red'
  }

  const dragDropHandler = (e: React.ChangeEvent<HTMLInputElement>, card: any) => {
    e.preventDefault()
    const newCardList = cardList.map(item => {
      if(item.id === card.id) {
        cardList.splice(card.id - 1, 1, currentCard)
      }
      if(item.id === currentCard.id) {
        cardList.splice(currentCard.id -1, 1, card)
      }
      return item
    })
    setCardList(newCardList)
    e.target.style.background = 'red'
  }
  
  const dragStartHandler = (card: any) => {
    setCurrentCard(card)
  }
  return (
    <div>
      {cardList.map(item => (
        <div 
          key={item.id}
          className='test'
          draggable={true}
          onDragOver={(e: any) => dragOverHandler(e)}
          onDragLeave={(e: any) => dragLeaveHandler(e)}
          onDrop={(e: any) => dragDropHandler(e, item)}
          onDragStart={(e: any) => dragStartHandler(item)}
        >
          <div>{item.id}</div>
          <div>{item.text}</div>
        </div>
      ))}
    </div>
  )
}
  • Вопрос задан
  • 116 просмотров
Решения вопроса 1
@SunUp
Я не волшебник, я ещё только учусь
В общем, у вас тут сразу несколько ошибок. Вот исправленный работающий пример, а теперь подробнее:
  1. Метод массивов splice изменяет исходный массив, и категорически не стоит использовать его напрямую на стейте, только на копии в коллбеке, это может приводить к весёлым ошибкам и увлекательному их поиску
  2. Цикл в вашем примере был абсолютно ни к чему, если вы использовали метод splice, который принимает напрямую индекс элемента для удаления/замены, тем более map, так как вы в нём возвращали item не изменяя его
  3. Даже при условии исправления предыдущих ошибок ваш пример корректно работать не будет так как после первого же перемещения id элемента больше не будет равен его текущему индексу в массиве, а вы пытаетесь из него получить это индекс
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы