[英]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.