【问题标题】:React js - Array doesn't update after a onSwipe() eventReact js - onSwipe() 事件后数组不更新
【发布时间】:2021-09-19 19:46:34
【问题描述】:

我是 Reactjs 的初学者,我刚刚开始使用 tinde-card-react 开发具有滑动功能的 Tinder 克隆。

我正在尝试使用 React useState() 更新两个变量,但不能。

主函数内部有 2 个主要组件,一个 TinderCards 组件以及左右滑动和回放按钮。问题是,当我手动刷卡时,变量不会更新,而当我使用按钮刷卡时,情况并非如此。

在当前日志中,我向右滑动卡片两次,并记录了变量alreadyRemovedpeople。变量 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;

我的控制台日志:

更新:

按照第一个答案的建议,我从 swiped() 函数中删除了 Timer,但问题仍然存在。

希望能得到更多的建议,以便解决这个问题。

【问题讨论】:

    标签: javascript reactjs firebase react-native


    【解决方案1】:

    我可以看到问题,但您可能需要弄清楚之后该怎么做。

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

    问题是 index 是从当前更新中计算出来的,但是到达下一个更新需要 1 秒,在这之间,您的 index 指向同一个,因为您的 index 来自people

    【讨论】:

    • 感谢您的回复。在 swipe() 函数中,我删除了计时器,但问题仍然存在。
    猜你喜欢
    • 2014-04-19
    • 2022-01-26
    • 1970-01-01
    • 1970-01-01
    • 2018-02-20
    • 2021-02-24
    • 2019-12-29
    • 1970-01-01
    相关资源
    最近更新 更多