reactjs 使用firebase snapShot读取react原生应用程序过多[已关闭]

pkbketx9  于 2023-03-08  发布在  React
关注(0)|答案(1)|浏览(106)

已关闭。此问题需要超过focused。当前不接受答案。
**想要改进此问题吗?**更新此问题,使其仅关注editing this post的一个问题。

昨天关门了。
Improve this question
我正在做一个react原生多人游戏。我用firebase firestore作为我的后台,有一个游戏使用了大量的读取,当我为更多的用户发布这个应用程序时,我一定会检查一下免费计划。我想知道是否有人可以调整代码,减少每个游戏的读取。

export function MultiGame({ route, navigation }) {
  const theme = useContext(themesContext);

  const getId = route.params.gameId;
  const getChosenDeck = route.params.getChosenDeckJoin;

  const { user } = useAuth();

  const [timeTill, setTimeTill] = useState(120);

  useEffect(() => {
    if (timeTill > 0) {
      const intervalId = setTimeout(() => {
        setTimeTill(timeTill - 1);
      }, 1000); // decrement timer every second

      return () => clearTimeout(intervalId);
    }
  }, [timeTill]);

  // useEffect(() => {
  //   if (bothPlayersJoined) {
  //     setTimeout(() => {
  //       setBothPlayersJoined(true);
  //     }, 3000);
  //   }
  // }, [firstLoadNum, bothPlayersJoined, bothPlayersInGame]);

  useEffect(() => {
    const docRef = doc(db, "games", getId);

    const checkIfData = onSnapshot(docRef, (doc) => {
      if (!doc.data()) {
        navigation.navigate("Home");
      }
    });

    const checkForPlayAgain = onSnapshot(docRef, (doc) => {
      if (doc.data()) {
        setUserOneClickPlayAgain(doc.data().userOneClickPlayAgain);
      } else {
        console.log("no data in doc.data()");
      }
    });

    const checkForBothPlayers = onSnapshot(docRef, (doc) => {
      if (doc.data()) {
        if (doc.data().playerOne && doc.data().playerTwo) {
          setPlayerTwo(doc.data().playerTwo);
        }
      } else {
        console.log("no data in doc.data()");
      }
    });

    // const delteAfterTime = onSnapshot(docRef, (doc) => {
    //   if (doc.data().playerOne && !doc.data().playerTwo && timeTill <= 0) {
    //     deleteDoc(docRef);
    //   }
    // });

    const unsubscribe = onSnapshot(docRef, (doc) => {
      if (doc.data().playerOne && doc.data().playerTwo) {
        setBothPlayersInGame(true);
        setGameDeck(JSON.parse(doc.data().gameDeck));

        setUserOneClickPlayAgain(doc.data().userOneClickPlayAgain);
        setMultiUserOneScore(doc.data().playerOneScore);
        setMultiUserTwoScore(doc.data().playerTwoScore);
        setMultiUserOneIndex(doc.data().playerOneIndex);
        setMultiUserTwoIndex(doc.data().playerTwoIndex);
        setCurrentIndex(doc.data().currentIndex);
        setPlayerOne(doc.data().playerOne);
        // setPlayerTwo(doc.data().playTwo);
        setRoundOverMulti(doc.data().roundOverMulti);
        setMultiNotInDeckOne(doc.data().multiNotInDeckOne);
        setMultiNotInDeckTwo(doc.data().multiNotInDeckTwo);
        setUserOneDeck(JSON.parse(doc.data().multiDefaultUserOne));
        setUserTwoDeck(JSON.parse(doc.data().multiDefaultUserTwo));
        setMultiStartDisabled(doc.data().multiStartDisabled);
        setNumberRounds(doc.data().numRounds);
      } else if (doc.data().playerOne && !doc.data().playerTwo) {
        setPlayerOne(doc.data().playerOne);
        setNumberRounds(doc.data().numRounds);

        if (
          !doc.data().gameDeck &&
          !doc.data().multiUserOneDeck &&
          !doc.data().multiUserTwoDeck
        ) {
          updateDoc(docRef, {
            gameDeck: stringDeck,
            multiDefaultUserOne: multiDefaultUserOne,
            multiDefaultUserTwo: multiDefaultUserTwo,
          });
        }
        if (doc.data().playerOne && !doc.data().playerTwo && timeTill <= 0) {
          deleteDoc(docRef);
        } else {
          // console.log("already hase deck");
        }
      } else {
        console.log("one player is in the game");
      }
    });
    return () => {
      unsubscribe();
      checkIfData();
      checkForPlayAgain();
      checkForBothPlayers();
    };
  }, [getId, timeTill]);

  useEffect(() => {
    const docRef = doc(db, "games", getId);

    const unsubscribe = onSnapshot(docRef, (doc) => {
      setGameCountDown(doc.data()?.gameCountDown);

      if (doc.data()?.playerOne !== null && doc.data()?.playerTwo) {
        if (getId === doc.data()?.id) {
          setTimeout(() => {
            // setGameCountDown(0);
            updateDoc(docRef, {
              gameCountDown: 0,
            });
          }, 3000);
        }
      }
    });

    return () => {
      unsubscribe();
    };
  }, [getId]);

  const getUSerChosenDeck = () => {
    if (getChosenDeck === "gameDecks") {
      return gameDecks;
    }
    if (getChosenDeck === "monsterDeck") {
      return monsterDeck;
    }
    if (getChosenDeck === "foodDeck") {
      return foodDeck;
    }
    if (getChosenDeck === "flagDeck") {
      return flagDeck;
    }
    if (getChosenDeck === "characterDeck") {
      return characterDeck;
    }
    if (getChosenDeck === "nhlDeck") {
      return nhlDeck;
    }
    if (getChosenDeck === "animalDeck") {
      return animalDeck;
    }
  };
  const shuffleArrayPreGame = (array) => {
    for (let i = array.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [array[i], array[j]] = [array[j], array[i]];
    }
    return array;
  };

  const shuffledArray = shuffleArrayPreGame(
    getUSerChosenDeck().map((deck) => shuffleArrayPreGame(deck))
  );

  const userOneRandom = (array) => {
    let randomIndex = Math.floor(Math.random() * array.length);
    if (randomIndex === 0) {
      randomIndex = 1;
    }
    return array[randomIndex];
  };
  let userOneChoice = userOneRandom(shuffledArray);

  const userTwoRandom = (array) => {
    let randomIndex = Math.floor(Math.random() * array.length);
    if (randomIndex === 0 || randomIndex === userOneChoice) {
      randomIndex = 1;
    }
    return array[randomIndex];
  };

  const multiDefaultUserOne =
    shuffledArray && JSON.stringify(userOneRandom(shuffledArray));
  const multiDefaultUserTwo =
    shuffledArray && JSON.stringify(userTwoRandom(shuffledArray));

  const stringDeck = shuffledArray && JSON.stringify(shuffledArray);

  const [numberRounds, setNumberRounds] = useState(0);

  const [currentIndex, setCurrentIndex] = useState(0);
  const [userTwoDeck, setUserTwoDeck] = useState();
  const [userOneDeck, setUserOneDeck] = useState();
  const [userOneScore, setUserOneScore] = useState(0);
  const [userTwoScore, setUserTwoScore] = useState(0);
  const [multiUserOneScore, setMultiUserOneScore] = useState();
  const [multiUserTwoScore, setMultiUserTwoScore] = useState();
  const [multiUserOneIndex, setMultiUserOneIndex] = useState();
  const [multiUserTwoIndex, setMultiUserTwoIndex] = useState();
  const [multiStartDisabled, setMultiStartDisabled] = useState();
  const [firstLoadNum, setFirstLoadNum] = useState(0);
  const [gameCountDown, setGameCountDown] = useState(3);

  const [timer, setTimer] = useState(120); // 2 minutes in seconds

  useEffect(() => {
    if (timer > 0) {
      const intervalId = setTimeout(() => {
        setTimer(timer - 1);
      }, 1000); // decrement timer every second

      return () => clearTimeout(intervalId);
    }
  }, [timer]);

  const formatTime = (count) => {
    const minutes = Math.floor(count / 60);
    const seconds = count % 60;
    const formatted = `${minutes.toString().padStart(2, "0")}:${seconds
      .toString()
      .padStart(2, "0")}`;
    return formatted;
  };

  const getDocData = async () => {
    const docRef = doc(db, "games", getId);

    const docSnap = await getDoc(docRef);
    if (docSnap.data().gameDeck) {
      //   console.log("Document data:", docSnap.data());
      //   const docSnap = await getDoc(docRef);
      const parse = JSON.parse(docSnap.data().gameDeck);
      setGameDeck(parse);
    } else {
      // doc.data() will be undefined in this case

      console.log("No such document!");
    }
  };

  useEffect(() => {
    getDocData();
  }, [getId]);

  const [gameDeck, setGameDeck] = useState([]);
  const [gameOver, setGameOver] = useState(false);
  const [multiNotInDeckOne, setMultiNotInDeckOne] = useState();
  const [multiNotInDeckTwo, setMultiNotInDeckTwo] = useState();
  const [roundOverMulti, setRoundOverMulti] = useState(true);
  const [showGameOverMessage, setShowGameOverMessage] = useState(false);
  const [progress, setProgress] = useState(0);
  const [bothPlayersInGame, setBothPlayersInGame] = useState(false);
  const [playerOne, setPlayerOne] = useState();
  const [playerTwo, setPlayerTwo] = useState();
  const [userOneClickPlayAgain, setUserOneClickPlayAgain] = useState();
  const [matchingID, setMatchingID] = useState();
  const [matchingIDTwo, setMatchingIDTwo] = useState();

  const [bothPlayersJoined, setBothPlayersJoined] = useState(true);

  const shortendEmail = playerOne ? playerOne.split("@")[0] : "";
  const shortendEmailTwo = playerTwo ? playerTwo.split("@")[0] : "Waiting...";

  const findMatchingIdUserOne = () => {
    gameDeck[currentIndex] &&
      gameDeck[currentIndex].forEach((gameDeckItem) => {
        let found = userOneDeck?.find((userDeckItem) => {
          return gameDeckItem.id === userDeckItem.id;
        });
        if (found) {
          setMatchingID(found.id);
          return;
        }
      });
  };

  const findMatchingIdUserTwo = () => {
    gameDeck[currentIndex] &&
      gameDeck[currentIndex].forEach((gameDeckItem) => {
        let found = userTwoDeck?.find((userDeckItem) => {
          return gameDeckItem.id === userDeckItem.id;
        });
        if (found) {
          setMatchingIDTwo(found.id);
          return;
        }
      });
  };

  useEffect(() => {
    findMatchingIdUserOne();
    findMatchingIdUserTwo();
    console.log(matchingID, "player one");
    console.log(matchingIDTwo, "player two");
  }, [currentIndex, gameDeck]);

  useEffect(() => {
    if (multiUserOneScore + multiUserTwoScore >= numberRounds) {
      // updateDoc(doc(db, "games", getId), {
      //   playerTwo: null,
      // });
      const timeout = setTimeout(() => {
        setGameOver(true);
      }, 900);
      return () => clearTimeout(timeout);
    }
  }, [multiUserOneScore, multiUserTwoScore, numberRounds]);

  useEffect(() => {
    if (multiStartDisabled) {
      const timeout = setTimeout(() => {
        updateDoc(doc(db, "games", getId), {
          multiStartDisabled: false,
        });
      }, 850);

      return () => clearTimeout(timeout);
    }
  }, [multiStartDisabled]);

  useEffect(() => {
    if (multiNotInDeckOne) {
      const timeout = setTimeout(() => {
        updateDoc(doc(db, "games", getId), {
          multiNotInDeckOne: false,
        });
      }, 1500);
      return () => clearTimeout(timeout);
    }
  }, [multiNotInDeckOne]);

  useEffect(() => {
    if (multiNotInDeckTwo) {
      const timeout = setTimeout(() => {
        updateDoc(doc(db, "games", getId), {
          multiNotInDeckTwo: false,
        });
      }, 1500);
      return () => clearTimeout(timeout);
    }
  }, [multiNotInDeckTwo]);

  useEffect(() => {
    if (numberRounds) {
      const totalScore = multiUserOneScore + multiUserTwoScore;
      const newProgress = totalScore / numberRounds;
      setProgress(newProgress);
    }
  }, [multiUserOneScore, multiUserTwoScore]);

  //write a useeffect that updates the progress bar when the score changes

  useEffect(() => {
    if (gameOver) {
      setTimeout(() => {
        setShowGameOverMessage(true);
        setTimeTill(120);
        updateDoc(doc(db, "games", getId), {
          userOneClickPlayAgain: false,
        });
      }, 500);
    }
  }, [gameOver]);

  const resetGame = () => {
    updateDoc(doc(db, "games", getId), {
      gameDeck: stringDeck,
      playerOneScore: 0,
      playerTwoScore: 0,
      playerOneIndex: 28,
      playerTwoIndex: 29,
      multiDefaultUserOne: multiDefaultUserOne,
      multiDefaultUserTwo: multiDefaultUserTwo,
      userOneClickPlayAgain: true,
      playerTwo: playerOne === user?.email ? null : user?.email,
      gameCountDown: 3,

      // roundOverMulti: true,
      // multiStartDisabled: true,
      // multiNotInDeckOne: false,
      // multiNotInDeckTwo: false,
      // multiRoundOver: true,
    });
    setBothPlayersJoined(true);
    setBothPlayersInGame(false);
    setUserOneScore(0);
    setUserTwoScore(0);

    setGameOver(false);
    setShowGameOverMessage(false);

    // setTimeout(
    //   () =>
    //     updateDoc(doc(db, "games", getId), {
    //       userOneClickPlayAgain: false,
    //     }),
    //   35000
    // );
  };

  const handleClick = (clickedEmoji, user) => {
    if (gameDeck[currentIndex].some((emoji) => emoji.id === clickedEmoji)) {
      if (user === "userOne") {
        setUserOneScore(userOneScore + 1);

        updateDoc(doc(db, "games", getId), {
          playerOneScore: userOneScore + 1,
          playerOneIndex: currentIndex,
          multiDefaultUserOne: JSON.stringify([...gameDeck[currentIndex]]),
        });
      } else {
        setUserTwoScore(userTwoScore + 1);
        updateDoc(doc(db, "games", getId), {
          playerTwoScore: userTwoScore + 1,
          playerTwoIndex: currentIndex,
          multiDefaultUserTwo: JSON.stringify([...gameDeck[currentIndex]]),
        });
      }

      updateDoc(doc(db, "games", getId), {
        roundOverMulti: false,
        multiStartDisabled: true,
      });

      setTimeout(
        () =>
          updateDoc(doc(db, "games", getId), {
            roundOverMulti: true,
          }),
        500
      );

      if (currentIndex === gameDeck.length - 1) {
        const beforeShuffle = gameDeck;
        shuffleArray(beforeShuffle);
        setGameDeck(beforeShuffle);

        setCurrentIndex(0);
      } else {
        updateDoc(doc(db, "games", getId), {
          currentIndex: currentIndex + 1,
        });
      }
    } else {
      if (user === "userOne") {
        updateDoc(doc(db, "games", getId), {
          multiNotInDeckOne: true,
        });
      } else {
        updateDoc(doc(db, "games", getId), {
          multiNotInDeckTwo: true,
        });
      }
    }
  };

  const shuffleArray = (array) => {
    for (let i = array.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [array[i], array[j]] = [array[j], array[i]];
    }
  };

  const goToHome = () => {
    setTimeout(() => {
      navigation.navigate("Home");
    }, 170);

    setTimeout(() => {
      deleteDoc(doc(db, "games", getId));
    }, 370);
  };

  const resetGameDelay = () => {
    setTimeout(() => {
      resetGame();
    }, 170);
  };

  const progressColor = "#263238";

  //if bother player not in game return waiting screen

  const shouldBeDisabledDeckOne = () => {
    if (playerOne === user?.email) return false;

    if (
      gameOver === true ||
      multiStartDisabled === true ||
      multiNotInDeckOne === true
    )
      return true;
    return false;
  };

  const shouldBeDisabled = () => {
    if (gameOver === true || multiStartDisabled === true) return true;
    if (playerOne === user?.email && multiNotInDeckOne) return true;
    if (playerOne !== user?.email && multiNotInDeckTwo) return true;
    if (gameCountDown === 3) return true;
    return false;
  };

我试着改变一些主要的使用效果,而不是一个快照,但没有工作得很好。

thtygnil

thtygnil1#

我从你的代码中可以理解的是,你在用户打开应用程序时调用firebase,如果用户的id存在,你就从数据库中提取数据。

解决方案为了减少firebase请求的数量,我建议您使用AsyncStorageCotextAPI

您可以保存每次用户打开应用时获取的用户基本详细信息,这将使您的应用响应更快,并根据您的要求减少firebase请求的数量。

相关问题