“useEffect"钩子只触发一次? [英] 'useEffect' hook only fires once?
问题描述
我正在为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数组中添加rounds
和currentGuess
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屋!