Старые реквизиты, используемые при рендеринге динамически отображаемого списка React / Redux - PullRequest
0 голосов
/ 01 декабря 2019

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

// Это хук, который создает список карт

const [cardDeck, setCardDeck] = useState([])
    useEffect(()=>{
        renderCardArray();
    },[props.news])

// Это функция, которая вызывает создателя действия

    const addToList = () =>{
        props.pushItemToReadingList(props.news[props.cardIndex]);
        props.increaseCardIndex();
}

// Это карта, для которой установлено значение состояния, которое я могу показать отдельно

const renderCardArray = () =>{
    if(props.news.length > 1 && props.cardIndex < props.news.length){
        setCardDeck(props.news.map((item,iter)=>{
            return(
                <div className="card" ref={drag} key={iter}>
                    <h3>{item.title}</h3>
                    <img src={item.urlToImage} alt='News' style={{maxWidth: '200px'}} />
                    <button onClick={props.increaseCardIndex}>X</button>
                    <button onClick={addToList}>{'<3'}</button>
                </div>
            )
            }))`

// Кнопка 2ed возвращает индекс 0 каждый клик, но карты обновляютсяс правильным индексом в окончательном возвращении // Вот окончательное возвращаемое значение компонента

return (
        <div>
            {cardDeck[props.cardIndex]}
        </div>
    )
}

// наконец, вот соединение и mapStateToProps

const mapStateToProps=(state)=>{
return {news: state.news, cardIndex: state.cardIndex}

}

export default connect(mapStateToProps,{
    pushItemToReadingList,
    increaseCardIndex
})(NewsCard);

Если кто-то может помочь мне понять, почему при выполнении функции addToList он не получает обновленный индекс, полученный остальным компонентом? Кроме того, есть ли лучший способ предоставить обновленный реквизит для сопоставленного списка? (Я временно решил эту проблему, переключив моего создателя действия, чтобы он не использовал аргумент push, он просто использует данные хранилища внутри, но это не помогает мнепонять, почему происходит такое поведение) (также я не планирую использовать локальное состояние и хранилище редуксов, я разделил их здесь просто для того, чтобы протестировать этот метод рендеринга и анимации карт без необходимости написания дополнительного создателя действий и редуктора для моегоcardDeck)

1 Ответ

0 голосов
/ 02 декабря 2019

Похоже, что в вашем массиве useEffect отсутствует зависимость props.cardIndex, поэтому он не обновляется при props.cardIndex обновлениях:

useEffect(()=>{
  if(props.news.length > 1 && props.cardIndex < props.news.length){
    renderCardArray();
  }
// renderCardArray depends on `props.cardIndex`, so
// make sure to add it here
},[props.news, props.cardIndex])

Было бы яснее, если бы содержимое renderCardArray были встроены в useEffect (если только вам не нужно вызывать эту функцию где-то еще). Вы также можете передать news и cardIndex в renderCardArray, чтобы прояснить, каковы зависимости.

renderCardArray(props.news, props.cardIndex);

Я не уверен, что это решит вашу проблему, но вот несколькопредложения, которые могут сделать код более понятным для / debug:

  1. Используйте значение для key, которое более стабильно, чем индекс. Индексы изменяются, если элементы добавляются / удаляются из массива, и это может вызвать ошибки. Если item.title уникален для каждого элемента, вы можете использовать его вместо этого.

  2. Установить данные в состояние и ограничить JSX тем, что вы возвращаете из своего компонента. Похоже, вам нужно рендерить только одну карту за раз, и вам может даже не понадобиться хранить что-либо в местном состоянии:

const item = props.news[props.cardIndex];

return (
  <div className="card" ref={drag}>
    <h3>{item.title}</h3>
    <img src={item.urlToImage} alt='News' style={{maxWidth: '200px'}} />
    <button onClick={props.increaseCardIndex}>X</button>
    <button onClick={addToList}>{'<3'}</button>
  </div>
)

Если вы делаете необходимо поддерживать массив карт в состоянии, хранить данные вместо JSX и отображать данные cardDeck при возврате:

const [cardDeck, setCardDeck] = useState([])

useEffect(()=>{
  if(props.news.length > 1 && props.cardIndex < props.news.length){
    setCardDeck(props.news);
  }
},[props.news, props.cardIndex]);
...
return (
  cardDeck.map(card => (
    <div className="card" ref={drag} key={card.title}>
      <h3>{card.title}</h3>
      <img src={card.urlToImage} alt='News' style={{maxWidth: '200px'}} />
      <button onClick={props.increaseCardIndex}>X</button>
      <button onClick={addToList}>{'<3'}</button>
    </div>
  )
)
Действия должны сообщать редуктору что , а не как . Они должны описывать, какое действие произошло, а не как редуктор должен обновлять состояние. Это сохраняет всю логику для состояния в одном месте (редуктор) и обеспечивает четкое разделение задач. Вместо pushItemToReadingList и increaseCardIndex вы можете отправить одно действие addItemToReadingList и позволить редуктору отвечать за его добавление в сохраненный список и увеличение индекса.
...