React - TypeError: Cannot read property 'img' of undefined
React - TypeError: Cannot read property 'img' of undefined
我正在使用 React 制作纸牌游戏,出于某种原因我得到 TypeError: Cannot read property 'img' of undefined
。
导致错误的代码:
import React, { useState } from "react";
import Card from "./components/Card";
const App = () => {
const [cards, setCards] = useState([
{
name: "King",
img: "https://image.freepik.com/free-vector/king-crown-esport-logo-design_177315-269.jpg",
pts: 10000,
},
{
name: "Minister",
img: "https://i.pinimg.com/474x/51/59/b3/5159b321713edef6c6a3b8f930f667a1.jpg",
pts: 5000,
},
{
name: "Cop",
img: "https://image.shutterstock.com/image-vector/police-officer-badge-icon-vector-260nw-613493573.jpg",
pts: 100,
},
{
name: "Thief",
img: "https://images1.livehindustan.com/uploadimage/library/2019/05/03/16_9/16_9_1/thief_symbolic_photo__1556892712.jpg",
pts: 0,
},
]);
const [shuffledCards, setShuffledCards] = useState([]);
for (let i = 0; i < 4; i++) {
const randCard = cards[Math.floor(Math.random() * (cards.length + 1))];
setShuffledCards([...shuffledCards, randCard]);
setCards(cards.filter((c) => c !== randCard));
}
return (
<div style={{ display: "flex", flexDirection: "row" }}>\
{shuffledCards.map((c) => (
<Card img={c.img} name={c.name} pts={c.pts} />
))}
</div>
);
};
export default App;
项目的link(在线Gitpod.io)-https://purple-salmon-uy3kza3n.ws-us10.gitpod.io/?folder=vscode-remote%3A%2F%2Fsapphire-quokka-1i5clgk7.ws-us09.gitpod.io%3A443%2Fworkspace(注意它可能会改变,一些奇怪的gitpod东西)
现在,当我在 for
循环中打印 shuffledCards
数组时,经过一些循环后,我注意到一个未定义的对象被添加到数组中。我认为这就是问题所在,我不知道它为什么会发生或如何发生,也不知道如何解决它。
期待收到你们的来信。在此先感谢您。
主要问题是你如何计算随机卡片,你正在索引数组。
const randCard = cards[Math.floor(Math.random() * (cards.length + 1))];
您要使用的长度。
const randCard = cards[Math.floor(Math.random() * (cards.length))];
另一个问题是您无条件地从组件主体更新状态,这将导致渲染循环。
将循环置于 useEffect
挂钩中并使用功能状态更新,因为您在循环中对状态更新进行排队。
useEffect(() => {
for (let i = 0; i < 4; i++) {
const randCard = cards[Math.floor(Math.random() * (cards.length))];
setShuffledCards((shuffledCards) => [...shuffledCards, randCard]);
setCards((cards) => cards.filter((c) => c !== randCard));
}
}, []);
存储两个数组是多余的。我会研究并实施 fisher-yates 洗牌。
这是一个示例效果:
useEffect(() => {
setCards((cards) => {
// create copy
const shuffledCards = cards.slice();
// shuffle
for (let i = cards.length - 1; i >= 0; i--) {
const randIndex = Math.floor(Math.random() * i);
[shuffledCards[i], shuffledCards[randIndex]] = [
shuffledCards[randIndex],
shuffledCards[i]
];
}
// return next state
return shuffledCards;
});
}, [shuffledCards]);
演示
在此演示中,我添加了一个随机播放按钮,这会更新 useEffect
依赖项以触发另一次随机播放。这种效果依赖性可以是您需要的任何东西,但对于您的特定用例,它可以被触发。
演示代码
const App = () => {
const [cards, setCards] = useState([
{
name: "King",
img:
"https://image.freepik.com/free-vector/king-crown-esport-logo-design_177315-269.jpg",
pts: 10000
},
{
name: "Minister",
img:
"https://i.pinimg.com/474x/51/59/b3/5159b321713edef6c6a3b8f930f667a1.jpg",
pts: 5000
},
{
name: "Cop",
img:
"https://image.shutterstock.com/image-vector/police-officer-badge-icon-vector-260nw-613493573.jpg",
pts: 100
},
{
name: "Thief",
img:
"https://images1.livehindustan.com/uploadimage/library/2019/05/03/16_9/16_9_1/thief_symbolic_photo__1556892712.jpg",
pts: 0
}
]);
const [shuffledCards, setShuffledCards] = useState(true);
const shuffle = () => setShuffledCards((t) => !t);
useEffect(() => {
setCards((cards) => {
const shuffledCards = cards.slice();
for (let i = cards.length - 1; i >= 0; i--) {
const randIndex = Math.floor(Math.random() * i);
[shuffledCards[i], shuffledCards[randIndex]] = [
shuffledCards[randIndex],
shuffledCards[i]
];
}
return shuffledCards;
});
}, [shuffledCards]);
return (
<>
<div style={{ display: "flex", flexDirection: "row" }}>
{cards.map((c) => (
<Card key={c.name} img={c.img} name={c.name} pts={c.pts} />
))}
</div>
<button type="button" onClick={shuffle}>
Shuffle Cards
</button>
</>
);
};
我正在使用 React 制作纸牌游戏,出于某种原因我得到 TypeError: Cannot read property 'img' of undefined
。
导致错误的代码:
import React, { useState } from "react";
import Card from "./components/Card";
const App = () => {
const [cards, setCards] = useState([
{
name: "King",
img: "https://image.freepik.com/free-vector/king-crown-esport-logo-design_177315-269.jpg",
pts: 10000,
},
{
name: "Minister",
img: "https://i.pinimg.com/474x/51/59/b3/5159b321713edef6c6a3b8f930f667a1.jpg",
pts: 5000,
},
{
name: "Cop",
img: "https://image.shutterstock.com/image-vector/police-officer-badge-icon-vector-260nw-613493573.jpg",
pts: 100,
},
{
name: "Thief",
img: "https://images1.livehindustan.com/uploadimage/library/2019/05/03/16_9/16_9_1/thief_symbolic_photo__1556892712.jpg",
pts: 0,
},
]);
const [shuffledCards, setShuffledCards] = useState([]);
for (let i = 0; i < 4; i++) {
const randCard = cards[Math.floor(Math.random() * (cards.length + 1))];
setShuffledCards([...shuffledCards, randCard]);
setCards(cards.filter((c) => c !== randCard));
}
return (
<div style={{ display: "flex", flexDirection: "row" }}>\
{shuffledCards.map((c) => (
<Card img={c.img} name={c.name} pts={c.pts} />
))}
</div>
);
};
export default App;
项目的link(在线Gitpod.io)-https://purple-salmon-uy3kza3n.ws-us10.gitpod.io/?folder=vscode-remote%3A%2F%2Fsapphire-quokka-1i5clgk7.ws-us09.gitpod.io%3A443%2Fworkspace(注意它可能会改变,一些奇怪的gitpod东西)
现在,当我在 for
循环中打印 shuffledCards
数组时,经过一些循环后,我注意到一个未定义的对象被添加到数组中。我认为这就是问题所在,我不知道它为什么会发生或如何发生,也不知道如何解决它。
期待收到你们的来信。在此先感谢您。
主要问题是你如何计算随机卡片,你正在索引数组。
const randCard = cards[Math.floor(Math.random() * (cards.length + 1))];
您要使用的长度。
const randCard = cards[Math.floor(Math.random() * (cards.length))];
另一个问题是您无条件地从组件主体更新状态,这将导致渲染循环。
将循环置于 useEffect
挂钩中并使用功能状态更新,因为您在循环中对状态更新进行排队。
useEffect(() => {
for (let i = 0; i < 4; i++) {
const randCard = cards[Math.floor(Math.random() * (cards.length))];
setShuffledCards((shuffledCards) => [...shuffledCards, randCard]);
setCards((cards) => cards.filter((c) => c !== randCard));
}
}, []);
存储两个数组是多余的。我会研究并实施 fisher-yates 洗牌。
这是一个示例效果:
useEffect(() => {
setCards((cards) => {
// create copy
const shuffledCards = cards.slice();
// shuffle
for (let i = cards.length - 1; i >= 0; i--) {
const randIndex = Math.floor(Math.random() * i);
[shuffledCards[i], shuffledCards[randIndex]] = [
shuffledCards[randIndex],
shuffledCards[i]
];
}
// return next state
return shuffledCards;
});
}, [shuffledCards]);
演示
在此演示中,我添加了一个随机播放按钮,这会更新 useEffect
依赖项以触发另一次随机播放。这种效果依赖性可以是您需要的任何东西,但对于您的特定用例,它可以被触发。
演示代码
const App = () => {
const [cards, setCards] = useState([
{
name: "King",
img:
"https://image.freepik.com/free-vector/king-crown-esport-logo-design_177315-269.jpg",
pts: 10000
},
{
name: "Minister",
img:
"https://i.pinimg.com/474x/51/59/b3/5159b321713edef6c6a3b8f930f667a1.jpg",
pts: 5000
},
{
name: "Cop",
img:
"https://image.shutterstock.com/image-vector/police-officer-badge-icon-vector-260nw-613493573.jpg",
pts: 100
},
{
name: "Thief",
img:
"https://images1.livehindustan.com/uploadimage/library/2019/05/03/16_9/16_9_1/thief_symbolic_photo__1556892712.jpg",
pts: 0
}
]);
const [shuffledCards, setShuffledCards] = useState(true);
const shuffle = () => setShuffledCards((t) => !t);
useEffect(() => {
setCards((cards) => {
const shuffledCards = cards.slice();
for (let i = cards.length - 1; i >= 0; i--) {
const randIndex = Math.floor(Math.random() * i);
[shuffledCards[i], shuffledCards[randIndex]] = [
shuffledCards[randIndex],
shuffledCards[i]
];
}
return shuffledCards;
});
}, [shuffledCards]);
return (
<>
<div style={{ display: "flex", flexDirection: "row" }}>
{cards.map((c) => (
<Card key={c.name} img={c.img} name={c.name} pts={c.pts} />
))}
</div>
<button type="button" onClick={shuffle}>
Shuffle Cards
</button>
</>
);
};