“useEffect"钩子只触发一次? [英] 'useEffect' hook only fires once?

查看:126
本文介绍了“useEffect"钩子只触发一次?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为React Native"开发一个猜谜游戏,用户输入一个数字,然后手机尝试猜出它.每次手机生成猜测时,用户都可以单击更大/更低".当用户输入数字并且计算机猜出彼此相等时,我们被带到游戏结束屏幕.

I am working of a Guessing Game for 'React Native' where the user enters a number and the phone tries to guess it. Each time the phone generates a guess the user can click Greater/Lower. When the user entered number and the computer made guess equal each other we are taken to the game over screen.

游戏结束屏幕未呈现.在屏幕上渲染游戏的逻辑放置在 useEffect()

The game over screen is not rendering. The logic to render the game over screen is placed inside of a useEffect()

问题

useEffect 在安装阶段只触发一次,以后再也不触发了?

useEffect is only fired once during the mounting phase and never again?

  const { userSelectedNumber, onGameOver } = props;
  useEffect(() => {
    console.log(currentGuess, userSelectedNumber);
    if (currentGuess === userSelectedNumber) {
      onGameOver(rounds);
    }
  }, [userSelectedNumber, onGameOver]);*emphasized text*

(./screens/GameScreen.js)

(./screens/GameScreen.js)

我们应该在 currentGuess === userSelectedNumber 时退出游戏屏幕,但此代码只运行一次.

We should exit the GameScreen when currentGuess === userSelectedNumber but this code is only run once.

以下 GameScreen 的完整代码:

Full code for GameScreen below:

import React, { useState, useRef, useEffect } from "react";
import { View, StyleSheet, Button, Text, Alert } from "react-native";

import NumberContainer from "../components/NumberContainer";
import Card from "../components/Card";

const randNumberGeneratorBetween = (min, max, exclude) => {
  min = Math.ceil(min);
  max = Math.floor(max);

  const randNum = Math.floor(Math.random() * (max - min)) + min;


  if (randNum === exclude) {
    return randNumberGeneratorBetween(1, 100, exclude);
  } else {
    return randNum;
  }
};

const GameScreen = props => {
  const [currentGuess, setCurrentGuess] = useState(
    randNumberGeneratorBetween(1, 100, props.userSelectedNumber)
  );
  const [rounds, setRounds] = useState(0);

  const currentLow = useRef(1);
  const currentHigh = useRef(100);

  const { userSelectedNumber, onGameOver } = props;

  useEffect(() => {
    console.log(currentGuess, userSelectedNumber);
    if (currentGuess === userSelectedNumber) {
      onGameOver(rounds);
    }
  }, [userSelectedNumber, onGameOver]);

  const nextGuessHandler = direction => {
    if (
      (direction === "lower" && currentGuess < props.userSelectedNumber) ||
      (direction === "greater" && currentGuess > props.userSelectedNumber)
    ) {
      Alert.alert("Don't Lie", "You know this is wrong", [
        { text: "Sorry", style: "cancel" }
      ]);
    }

    if (direction === "lower") {
      currentHigh.current = currentGuess;
    } else {
      currentLow.current = currentGuess;
    }
    const nextNumber = randNumberGeneratorBetween(
      currentLow.current,
      currentHigh.current,
      currentGuess
    );
    console.log('nextNumber',nextNumber);
    setCurrentGuess(nextNumber);

    setRounds(currRounds => currRounds + 1);
    console.log('currRound',rounds);

  };

  return (
    <View style={styles.screen}>
      <Text>Opponents Guess</Text>
      <NumberContainer>{currentGuess}</NumberContainer>
      <Card style={styles.buttonContainer}>
        <Button
          title="Lower"
          onPress={nextGuessHandler.bind(this, "lower")}
        ></Button>
        <Button
          title="Greater"
          onPress={nextGuessHandler.bind(this, "greater")}
        ></Button>
      </Card>
    </View>
  );
};

const styles = StyleSheet.create({
  screen: {
    flex: 1,
    padding: 10,
    alignItems: "center"
  },
  buttonContainer: {
    flexDirection: "row",
    justifyContent: "space-between",
    marginTop: 20,
    width: 300,
    maxWidth: "80%"
  }
});

export default GameScreen;

项目可以在这里找到:https://codesandbox.io/s/github/SMasood1/guessingGame?file=/screens/GameScreen.js:852-1039

推荐答案

需要在useEffect钩子中的dependencies数组中添加roundscurrentGuess

You need to add rounds and currentGuess to the dependencies array in the useEffect hook

 useEffect(() => {
    console.log(currentGuess, userSelectedNumber);
    if (currentGuess === userSelectedNumber) {
      onGameOver(rounds);
    }
  }, [userSelectedNumber, onGameOver,currentGuess,rounds]);

使用 props 初始化状态也被认为是一种反模式,所以我建议添加另一个 useEffect 钩子:

Also it is considered a anti-pattern to use props to initialize a state, so I would recommend to add an other useEffect hook:

useEffect(()=>{
    setCurrentGuess(randNumberGeneratorBetween(1, 100, props.userSelectedNumber))

},[props.userSelectedNumber]);

这篇关于“useEffect"钩子只触发一次?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆