[英]Why is my hooks states going back to its initial states?
我一直在制作一款游戏,最后要求用户输入他们的猜测。 为了避免在我的实际项目中造成混淆,我在 codesandbox 中创建了一些东西来演示我遇到的问题。 我应该补充一点,codesandbox 中的游戏没有多大意义。 但本质上,您只需单击任何框 5 次即可生成一个随机数,当组件安装时,它还会创建一个包含 5 个随机数的数组。 最后,您键入一个数字,它会检查 arrays 是否包含输入的密钥,并相应地检查 colors 是否包含它们。 我遇到的问题是,一旦显示了猜测组件,所有挂钩状态都会返回到它们的初始状态。
主要.tsx
import { Guess } from "./Guess";
import { useHook } from "./Hook";
import { Loading } from "./Loading";
import "./styles.css";
export const Main = () => {
const {loading, count, handleClick, randArr} = useHook()
return (
<div className="main">
{!loading && count < 5 &&
<div className='click-container'>
{Array.from({length: 5}).fill('').map((_, i: number) =>
<div onClick={handleClick} className='box' key={i}>Click</div>
)}
</div>
}
{loading && <Loading count={count} />}
{!loading && count >= 5 && <Guess arr={randArr} />}
</div>
);
}
钩子.tsx
import { useEffect, useState } from 'react'
export const useHook = () => {
type guessType = {
keyNum: number
isContain: boolean
}
const [disable, setDisable] = useState(true)
const [randArr, setRandArr] = useState<number[]>([])
const [initialArr, setInitialArr] = useState<number[]>([])
const [count, setCount] = useState<number>(0)
const [loading, setLoading] = useState(true)
const [guess, setGuess] = useState<guessType[]>([])
const randomNum = () => {
return Math.floor(Math.random() * (9 - 0 + 1) + 0);
}
useEffect(() => {
const handleInitialArr = () => {
for (let i = 0; i < 5; i++) {
let num = randomNum()
setInitialArr((prev) => [...prev, num])
}
}
handleInitialArr()
}, [])
const handleClick = () => {
if (!disable) {
let num = randomNum()
setRandArr((prev)=> [...prev, num])
setCount((prev) => prev + 1)
setDisable(true)
setLoading(true)
}
}
useEffect(()=> {
const handleLoading = () => {
setTimeout(() => {
setLoading(false)
}, 500)
}
const handleRound = () => {
setDisable(false)
}
handleLoading()
handleRound()
}, [count])
const handleKeyUp = ({key}) => {
const isNumber = /^[0-9]$/i.test(key)
if (isNumber) {
if (randArr.includes(key) && initialArr.includes(key)) {
setGuess((prev) => [...prev, {keyNum: key, isContain: true}])
console.log(' they both have this number')
} else {
setGuess((prev) => [...prev, {keyNum: key, isContain: false}])
console.log(' they both do not contain this number ')
}
}
}
console.log(count)
console.log(randArr, ' this is rand arr')
console.log(initialArr, ' this is initial arr')
return {
count,
loading,
handleClick,
randArr,
handleKeyUp,
guess
}
}
猜猜.tsx
import React, { useEffect } from "react";
import { useHook } from "./Hook";
import "./styles.css";
type props = {
arr: number[];
};
export const Guess: React.FC<props> = (props) => {
const { handleKeyUp, guess } = useHook();
useEffect(() => {
window.addEventListener("keyup", handleKeyUp);
return () => {
window.removeEventListener("keyup", handleKeyUp);
};
}, [handleKeyUp]);
console.log(props.arr, " this is props arr ");
return (
<div className="content">
<div>
<p>Guesses: </p>
<div className="guess-list">
{guess.map((item: any, i: number) =>
<p key={i} className={guess[i].isContain ? 'guess-num-true': 'guess-num-false'} >{item.keyNum}</p>
)}
</div>
</div>
</div>
);
};
另外,如果你想自己看看,这里是 codesandbox: https://codesandbox.io/s/guess-numbers-70fss9
任何帮助将不胜感激!!!
固定演示: https://codesandbox.io/s/guess-numbers-fixed-kz3qmw?file=/src/my-context.tsx:1582-2047
您误以为挂钩在组件之间共享 state。 每次调用useHook()
时,钩子都会有一个新的 state。 要共享 state,您需要使用Context
。
type guessType = {
keyNum: number;
isContain: boolean;
};
type MyContextType = {
count: number;
loading: boolean;
handleClick: () => void;
randArr: number[];
handleKeyUp: ({ key: string }) => void;
guess: guessType[];
};
export const MyContext = createContext<MyContextType>(null as any);
export const MyContextProvider: FC<PropsWithChildren<{}>> = ({ children }) => {
// Same stuff as your hook goes here
return (
<MyContext.Provider
value={{ count, loading, handleClick, randArr, handleKeyUp, guess }}
>
{children}
</MyContext.Provider>
);
};
export const App = () => {
return (
<div className="App">
<MyContextProvider>
<Page />
</MyContextProvider>
</div>
);
};
export const Main = () => {
const { loading, count, handleClick, randArr } = useContext(MyContext);
...
}
export const Guess: React.FC<props> = (props) => {
const { handleKeyUp, guess } = useContext(MyContext);
...
}
你的handleKeyUp
function 也被窃听了,这是一个很好的例子,说明为什么你需要输入你的参数。 key
是字符串,不是数字。 所以条件永远是假的。
const handleKeyUp = ({ key }: {key: string}) => {
const num = parseInt(key);
if (!isNaN(num)) {
if (randArr.includes(num) && initialArr.includes(num)) {
setGuess((prev) => [...prev, { keyNum: num, isContain: true }]);
console.log(" they both have this number");
} else {
setGuess((prev) => [...prev, { keyNum: num, isContain: false }]);
console.log(" they both do not contain this number ");
}
}
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.