Js — массив React не обновляется после события OnSwipe()

# #javascript #reactjs #firebase #react-native

Вопрос:

Я новичок в Reactjs и только начал работать над клоном Tinder с функцией салфетки, используя tinde-card-react.

Я пытаюсь обновить две переменные с помощью React useState (), но не могу.

Внутри основной функции есть 2 основных компонента: компонент TinderCards и кнопки прокрутки вправо и влево и воспроизведения. Проблема в том, что, когда я провожу карты вручную, переменные не обновляются, и это не тот случай, когда я провожу с помощью кнопок.

В текущем журнале я дважды прокрутил карточки вправо и зарегистрировал переменные уже перемещенные и люди. Переменная people изначально представляет собой массив, содержащий 3 объекта, поэтому после второго свайпа предполагается регистрировать только 2 объекта, а не 3, в то время как переменная alreadyRemoved должна обновляться до недостающих элементов переменной people.

Это мой код :

 import React, { useState, useEffect, useMemo } from 'react';
import './IslamCards.css';
import Cards from 'react-tinder-card';
import database from './firebase';
import hate from "./Cross.png"
import replayb from "./Replay.png"
import love from "./Love.png"
import IconButton from "@material-ui/core/IconButton"


function IslamCards(props) {
  let [people, setPeople] = useState([])

  useEffect(() => {
    database.collection("People").onSnapshot(snapshot => { setPeople(snapshot.docs.map(doc => doc.data())) })
  }, [])

  let [alreadyRemoved , setalreadyRemoved] = useState([])


  let buttonClicked = "not clicked"

 // This fixes issues with updating characters state forcing it to use the current state and not the state that was active when the card was created.

  let childRefs = useMemo(() => Array(people.length).fill(0).map(() => React.createRef()), [people.length])

  

  let swiped = () => {

    
    if(buttonClicked!=="clicked"){
      console.log("swiped but not clicked")
      if(people.length){
      let cardsLeft = people.filter(person => !alreadyRemoved.includes(person))
      if (cardsLeft.length) {

          let toBeRemoved = cardsLeft[cardsLeft.length - 1] // Find the card object to be removed
          let index = people.map(person => person.name).indexOf(toBeRemoved.name)// Find the index of which to make the reference to
          setalreadyRemoved(list => [...list, toBeRemoved])


          setPeople(people.filter((_, personIndex) => personIndex !== index))
          console.log(people)
          console.log(alreadyRemoved)

    }
  }
    buttonClicked="not clicked"

  }
  }

  let swipe = (dir) => {
    buttonClicked="clicked"
    console.log("clicked but not swiped")
    if(people.length){
    let cardsLeft = people.filter(person => !alreadyRemoved.includes(person))
  
    if (cardsLeft.length) {

      let toBeRemoved = cardsLeft[cardsLeft.length - 1] // Find the card object to be removed
      let index = people.map(person => person.name).indexOf(toBeRemoved.name)// Find the index of which to make the reference to
      setalreadyRemoved(list => [...list, toBeRemoved])

      childRefs[index].current.swipe(dir)
      
      
      let timer =setTimeout(function () {

      setPeople(people.filter((_, personIndex) => personIndex !== index))}
      , 1000)
      
      console.log(people)
      console.log(alreadyRemoved)
    }

      // Swipe the card!
    }
  }

  let replay = () => {
    let cardsremoved = alreadyRemoved
      console.log(cardsremoved)
    if (cardsremoved.length) {
      let toBeReset = cardsremoved[cardsremoved.length - 1] // Find the card object to be reset
      console.log(toBeReset)
      setalreadyRemoved(alreadyRemoved.filter((_, personIndex) => personIndex !== (alreadyRemoved.length-1)))
      if (!alreadyRemoved.length===0){ alreadyRemoved=[]}
      let newPeople = people.concat(toBeReset)
      setPeople(newPeople)

      // Make sure the next card gets removed next time if this card do not have time to exit the screen
    }

  }

  return (
    <div>
      <div className="cardContainer">
        {people.map((person, index) => {
          return (
            <Cards ref={childRefs[index]} onSwipe={swiped}  className="swipe" key={index} preventSwipe={['up', 'down']}>
              <div style={{ backgroundImage: `url(${person.url})` }} className="Cards">
                <h3>{person.name}</h3>
              </div>
            </Cards>);
        })}
      </div>
      <div className="reactionButtons">
        <IconButton onClick={() => swipe('left')}>
          <img id="hateButton" alt="d" src={hate} style={{ width: "10vh", marginBottom: "5vh", pointerEvents: "all" }} />
        </IconButton>
        <IconButton onClick={() => replay()}>
          <img id="replayButton" alt="e" src={replayb} style={{ width: "11vh", marginBottom: "5vh", pointerEvents: "all" }} />
        </IconButton>
        <IconButton onClick={() => swipe('right')}>
          <img id="loveButton" alt="f" src={love} style={{ width: "11vh", marginBottom: "5vh", pointerEvents: "all" }} />
        </IconButton>
      </div>
    </div>

  );
}

export default IslamCards;
 

Мой журнал консоли :

введите описание изображения здесь

Обновить :

Как было предложено в 1-м ответе, я удалил таймер из функции swiped (), но проблема не исчезла.

Я надеюсь получить больше предложений, чтобы я мог решить эту проблему.

Ответ №1:

Я вижу проблему, но вам, возможно, придется решить, что делать после этого.

       setPeople(people.filter((_, personIndex) => personIndex !== index))}
      , 1000)
 

Проблема в том, что index это выясняется из текущего обновления, однако для перехода к следующему обновлению требуется 1 секунда, в промежутке между ними вы index указываете на одно и то же, потому index что оно является производным от people .

Комментарии:

1. Спасибо вам за ваш ответ. В функции swiped() я удалил таймер, но проблема не исчезла.