[英]React after updating an object's state with useState hook, I can't call any of its functions
我正在为上下文制作一个二十一点算牌培训应用程序。
它目前处理卡片并具有基本的hit
功能,我在处理拆分(太多嵌套数组)时遇到了复杂性,所以我想我会制作一个Players
和Player
对象,但我在尝试更新时遇到了问题state 与useState
挂钩。
主要问题是我显然使用useState()
钩子错误地更新了对象 state。 我幼稚的假设是,如果我有我的players
器 object 及其内部 state,我调用函数来更新 state,然后做一个简单的setPlayers(players)
。 我在网上读到因为它是 object,所以你必须对其进行深度复制,以便 React 将其识别为新的 object 或类似的东西。 当我执行上述想法时,我的useEffect()
钩子对players
更新做出反应,从不执行 - 所以它没有接受 object 更改。 另一方面,我的用户界面确实更新了……这让我很困惑。
我尝试了许多在网上找到的不同方法(有很多关于此的帖子,但每个解决方案都给我同样的错误,让我觉得我只是不理解某些东西),但都取得了不同程度的成功。 如果我做
setPlayers({...players})
我的useEffect
钩子的执行方式与setPlayers(player)
不同。 问题在于这样做,在调用setPlayers({..players})
之后,我在处理后尝试第二次击中时收到以下错误。 我可以处理,然后点击一次,然后我得到以下信息: Uncaught TypeError: players.hit is not a function
。 我使用回调找到了其他解决方案,但我得到了同样的错误。
我做了一个Players
和Player
class(不是组件)来处理一些手部逻辑。 我遇到了处理拆分二十一点手的复杂性,所以我想我会将其抽象为 class。 我很确定将这些类与useState()
一起使用会让我遇到问题。 我查看了有关更新 object 以便重新渲染的其他帖子,它们会产生不同的行为,但我真的不想要...
所以我的Players
和Player
class 是非常有状态的,许多函数不返回值,他们只是更新他们的内部hands
state。
这是我的Players
和Player
class。
class Players {
constructor(numPlayers) {
this.numPlayers = numPlayers;
this.players = new Array(numPlayers).fill().map( () => (new Player()));
this.currentPlayer = 0;
}
hit(card) {
this.players[this.currentPlayer].hit(card);
}
}
class Player {
constructor() {
this.hands = [[]];
this.currentHand = 0; // for splits
this.numHands = 1;
this.double = false;
}
getCurrentHand() {
return this.hands[this.currentHand];
}
hit(card) {
this.getCurrentHand().push(card);
return this.hands;
}
//other functions like split() here, omitting for clarity.
这是我的应用程序启动的地方。 我让我的players
和setPlayers
。 所有这些都按预期工作,它初始化了它需要的 state,当一切准备就绪时,它会分发卡片。 我在屏幕上看到了我想要的卡片。 我将把我的Hands
组件放在最后,所以这不是所有的浮动代码,但它与我不认为的问题无关。
export default function App() {
const [deck, setDeck] = useState(initDeck());
const [count, setCount] = useState(0);
const [players, setPlayers] = useState(new Players(numPlayers));
useEffect(() => {
deal(deck, count, setCount, players, setPlayers);
}, []);
useEffect(() => {
console.log(players);
}, [players])
}
这就是我的问题所在:我经历了很多不同的方式,在 App 中,如何使用setPlayers()
。 我不会发布我所有的尝试,但所有结果要么是useEffect
钩子没有在更改时执行,要么当我之前使用它时说某事不是 function。 它以某种方式错误地复制了 object 并失去了调用任何 function 的能力......
这是我在应用程序中的hit
function,我正在处理我的const [players, setPlayers] = useState(new Players(numPlayers));
我一开始就创造了。
我没有遇到setCount
的任何问题,因为它只是一个简单的 integer。
function hit(deck, count, setCount, players, setPlayers) {
let card = deck.pop();
setCount(incrementCardCount(card, count));
players.hit(card);
setPlayers({...players}); // this updates with the useEffect([players]). Others don't.
}
我也尝试过奇怪的东西,比如在 function 开头的let newPlayers = players
player ,然后尝试setPlayers(newPlayers)
,但这些奇怪的解决方案都没有我试图解决手头的问题。 感觉就像我完全错过了 React 的基本内容,或者对象或其他东西上的useEffect
或useState
Hands
组件只是放在这里,与问题无关。 它循环播放我的Players
并在我想要的屏幕上显示他们的牌。
return (
<View key={styles.playerHands}>
{props.players.players.map((player, i) =>
<View key={`player-${i}`} style={styles.player}>
{player.hands.map((cards, j) =>
<View key={`player-${i}-${j}`} style={styles.hand}>
{cards.map((card, k) =>
<Image key={`player-${i}-${j}-${k}`} style={createCardOverlap(k, j)} resizeMode={'contain'} source={displayCard(card)} />
)}
</View>
)}
</View>
)}
</View>
)
希望这已经得到了充分的解释,重申我正在尝试了解如何在我的Players
obj 上使用setPlayers()
。 我很困惑如何做到这一点setPlayers({...players});
完全剥夺了它调用任何函数的能力,并且在我调用player
上的一些函数以更新其 state 之后,我不知道如何解决明显的setPlayers(players)
问题。
我这样做是否正确,因为感觉就像我错过了一些东西。 所有更新 state 都发生在 App 中,我的Players
obj 只是正常更新其内部 state。
谢谢
setPlayers({...players});
创建一个新的普通 object 并用players
自己的公共数据属性填充它。 它不会创建Players
实例; 普通的 object 没有正确的原型,也没有被Player
构造函数初始化。 为此,您需要调用new Players
。
我发现我很少使用 state 中的对象,这些对象不仅仅是普通对象(传播适用),但有时它很方便。 如果要使用Players
,则需要更新Players
以提供一种通过必要的更改创建新Players
object 的方法。
FWIW,我不会有Players
class,它似乎没有提供太多东西。 我只需要一个Players
数组并将currentPlayer
保存在 state 中。 然后让Player.prototype.hit
返回一个新的、更新的Player
object。 Since objects in state must not be directly modified , you'd probably want to write Player
using immutable methodology (methods don't modify the state of the object, they return a new object with the updated state).
附带说明一下,“ 不要直接修改 state ”规则似乎正在hit
以下几个方面:
pop
on deck
直接修改了deck
的 state。hit
this.players[this.currentPlayer]
(在Players.prototype.hit
)直接修改Players
中的播放器 object 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.