意外使用影响行为

  • 本文关键字:影响 意外 reactjs
  • 更新时间 :
  • 英文 :


我正在制作刽子手游戏。当字母被点击时,它不应该再被点击了。

这是代码沙箱上的简化版本: https://codesandbox.io/s/intelligent-cori-6b80q

在沙盒中,单击字母时,它将更改为"单击!这里的一切似乎都很好。

但是在我的项目中,我得到了奇怪的行为。

可用信件.js

const AvailableLetter = (props) => {
const [clicked,setClicked]=useState(false);
const setStuff = () => {
setClicked(false); // If I delete this I get Error: Maximum update depth exceeded.
props.setSolved();
};
useEffect( setStuff,[clicked] );
if (clicked)         // IF CLICKED REMAINS TRUE, EVERY LETTER GETS PLAYED.
{
if (props.play())
{
props.correct();
}
else
{
props.incorrect();
}
}
const disableLetter = () => {
setClicked(true);
};
let letter=span onClick={disableLetter}>{props.alphabet}</span>;
if(clicked)    // CODE NEVER GETS HERE!!!!!!!!!!!!!!
{
letter = <span>{props.alphabet}</span>;
}
return (
<Ax>                 // Ax is a high order class, just a wrapper
{letter}
</Ax>
);
}

即使被点击,字母仍然可点击。这不是我想要的。

每个字母都由 Letters 呈现.js Letters 以 a-z 为单位输入并生成自定义 AvailableLetter。

const availableLetters = [ ...allLetters ].map(
(alphabet,i) => {
return (
<AvailableLetter setSolved={props.setSolved} play={()=>playHandler(alphabet)} correct={()=>props.correct(alphabet)} incorrect={()=>props.incorrect(alphabet)} solution={props.solution} key={i} alphabet={alphabet} />
);
}
);

所以这里要解决的问题是:

- Letters remain clickable even after a click
- If setClicked(false) is removed it causes an infinite loop
const setStuff = () => {
setClicked(false);    // if removed causes infinite loop
props.setSolved();
};

所有这些都很奇怪,因为在代码沙箱中,我不需要在setEffect((中将clicked设置为false。

您可以在此处查看所有代码:https://github.com/gunitinug/hangmanerrors/tree/master/src 请看一下项目代码,它不长。

您需要了解useEffect的工作原理。每当状态发生变化时,都会调用useEffect,并且作为回调传递给useEffect的处理程序(在您的情况下setStuff(被执行。

因此,setStuff不断更新状态,useEffect不断被调用。因此,您会看到错误Error: Maximum update depth exceeded.

更改代码,如下所示:

const AvailableLetter = (props) => {
const [clicked, setClicked] = useState(false);
const setStuff = () => {
if(clicked) {
if (props.play()) {
props.correct();
}
else {
props.incorrect();
}
setClicked(false);
props.setSolved();
}
};
useEffect( setStuff, [clicked] );
return (
<Ax>
<button onClick={() => setClicked(true)} disabled={clicked}>{props.alphabet}</button>
</Ax>
);
}

正如在您的问题发表的评论中提到的,这可能不是最好的方法,但我的代码应该可以解决您的问题。

这是一个结构问题,我不得不将处理程序函数和状态委托给父组件 Letters.js

我必须让它工作如丝般光滑:p

import React, {useState} from 'react';
import AvailableLetter from './AvailableLetter/AvailableLetter';
import DisabledLetter from './DisabledLetter/DisabledLetter';
import classes from './Letters.module.css';
const Letters = (props) => {
const [lettersMap, setLettersMap]=useState(
{
"a":false,"b":false,"c":false,"d":false,"e":false,"f":false,"g":false,"h":false,"i":false,"j":false,"k":false,"l":false,"m":false,"n":false,"o":false,"p":false,"q":false,"r":false,"s":false,"t":false,"u":false,"v":false,"w":false,"x":false,"y":false,"z":false
}
);
const updateClickedHandler = (letter) => {
setLettersMap(
{
...lettersMap,[letter]:true
}
);
};
const playHandler = (alphabet) => {
const solution = props.solution.split('');
console.log(solution);
if (solution.indexOf(alphabet)<0)
{
console.log('incorrect');
return false;
}
else
{
console.log('correct');
return true;
}
}
const renderedLetters = Object.keys(lettersMap).map(
(letter,i)=>{
if (!lettersMap[letter])     //letter is not yet clicked
{
return (
<AvailableLetter updateClicked={updateClickedHandler} setSolved={props.setSolved} play={()=>playHandler(letter)} correct={()=>props.correct(letter)} incorrect={()=>props.incorrect(letter)} solution={props.solution} key={i} alphabet={letter} />
)
}
else                         //letter is clicked
{
return (
<DisabledLetter alphabet={letter} />
)
}
}
);

return (    
<div className={classes.Letters}>
<p>Solution: {props.solution}</p>
<div className={classes.AvailableLetters}>
{renderedLetters}
</div>
</div>
);
}
export default Letters;

import React from 'react';
import classes from './AvailableLetter.module.css';
import Ax from '../../hoc/Ax';
const AvailableLetter = (props) => {
const setStuff = () => {
if (props.play()) {
props.correct();
}
else {
props.incorrect();
}
props.updateClicked(props.alphabet);
props.setSolved();
};
return (
<Ax>
<span className={classes.AvailableLetter} onClick={setStuff}>{props.alphabet}</span>
</Ax>
);
}
export default AvailableLetter;

最后,我添加了另一个名为DisabledLetter的组件.js

import React from 'react';
import classes from './DisabledLetter.module.css';
const DisabledLetter = (props) => {
return (
<span className={classes.DisabledLetter} >{props.alphabet}</span>
);
};
export default DisabledLetter;

您可以在此处查看整个源代码 https://github.com/gunitinug/hangmanclicked/tree/master/src ;)

发现了一个问题,当游戏解决时,我需要再单击一个字母才能显示"YOU win"消息。

当我死后,"游戏结束"立即显示。

最新更新