使用三元运算符取消重复显示的可能性
cancelling out possibility of repeat display using ternary operator
我正在使用 React 构建一个抽认卡应用程序,以帮助保留编程概念。到目前为止,我已将应用程序设置为在卡片正面显示带有概念 definition/explanation 并在背面显示相应的 term/concept 的卡片。用户可以翻转卡片并通过单击按钮更改为另一张卡片。问题是目前,onClick 有时会显示之前显示的卡片。我想防止这种情况发生。我尝试使用三元运算符这样做,但不知何故,我的 Javascript 逻辑是错误的,因为我仍然得到重复显示。我该如何解决这个问题?
代码如下:
// data and components
import { conceptArray } from "./data";
import FlashCard from "./components/FlashCard";
function App() {
const [randomCard, setRandomCard] = useState({});
const [mode, setMode] = useState(true);
// this should store the individual concept (individual items in the concept Array) to later be displayed as a card
const getCard = () => {
// this changes the card and posits that there can be no repeat display of card that was displayed immediately before
let newCard = conceptArray[Math.floor(Math.random() * conceptArray.length)];
newCard !== randomCard ? setRandomCard(newCard) : newCard = conceptArray[Math.floor(Math.random() * conceptArray.length)];
// this allows for the front of the card(ie. the definition) to be displayed
setMode(true);
};
const flip = () => {
// this allows for the back of the card (ie. the term itself) to be displayed
setMode(!mode);
}
console.log(randomCard);
return (
<div className="App">
<header className="App-header">
<FlashCard randomCard={randomCard} mode={mode} />
<button onClick={getCard}>Get FlashCard</button>
<button onClick={flip}>Flip</button>
</header>
</div>
);
}
export default App;
如果您参考 this 关于 SOF 的问题,可以应用许多解决方案。
请检查这个函数,如果你需要随机数组,也许你可以全局使用它,只需传递数组长度
const generate_random_number = (_objLength) => {
let random_array_of_integers = [];
while (random_array_of_integers.length < _objLength) {
let random_integer = Math.floor(Math.random() * _objLength);
if (!random_array_of_integers.includes(random_integer))
random_array_of_integers.push(random_integer);
}
return random_array_of_integers;
}
所以我最终接受了将 conceptArray 改组为状态的建议。我使用 Fisher-Yates(又名 Knuth)Shuffle 这样做,可以在这里找到:How to randomize (shuffle) a JavaScript array?。我还不完全理解它背后的逻辑,但我能够将它应用到我的代码中并让它工作。现在,卡片以随机顺序抽取,不会立即重复。
正如 Thomas Wikman 如此简洁地解释的那样,这就像洗牌 conceptArray 中的项目,类似于洗牌的方式。一旦发生这种情况,我使用 onClick 从该数组中获取第一个项目,过滤掉数组以排除被获取的概念,然后继续获取另一个。完成数组中的最后一个概念后,我会再次执行随机播放并重新开始。
如果这对其他人有帮助,这里是结果代码:
// data and components
import { conceptArray } from "./data";
import FlashCard from "./components/FlashCard";
import AddForm from "./components/AddForm";
function App() {
// Fisher-Yates (aka Knuth) Shuffle
// don't completely understand it but I got it to work
const shuffle = array => {
var currentIndex = array.length, temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
// puts shuffled array of concepts into state
const [cardArray, setCardArray] = useState(shuffle(conceptArray));
const [randomCard, setRandomCard] = useState({});
const [frontMode, setFrontMode] = useState(true);
const [formMode, setFormMode] = useState(false);
// stores the individual concept (individual item in the concept Array) to be displayed as a card
const getCard = () => {
// grabs the first item in the shuffled array
setRandomCard(cardArray[0]);
// filters array so that item already displayed on card cannot be shown again until array is reshuffled
setCardArray(cardArray.filter(item => item !== cardArray[0]));
// when there is only one item left in filtered array, shuffles entire array again
if (cardArray.length === 1) {
setCardArray(shuffle(conceptArray));
}
// this allows for the front of the card(ie. the definition) to be displayed
setFrontMode(true);
};
const flip = () => {
// this allows for the back of the card (ie. the term itself) to be displayed
setFrontMode(!frontMode);
}
const renderForm = () => {
setFormMode(true);
}
// console.log(randomCard);
// console.log(conceptArrayRandomized);
// console.log(conceptArray);
return (
<div className="App">
{!formMode && <FlashCard randomCard={randomCard} frontMode={frontMode} />}
{!formMode && <button onClick={getCard}>Get FlashCard</button>}
{!formMode && <button onClick={flip}>Flip</button>}
<br />
{!formMode && <button onClick={renderForm}>Add New</button>}
{formMode && <AddForm />}
</div>
);
}
export default App;
我正在使用 React 构建一个抽认卡应用程序,以帮助保留编程概念。到目前为止,我已将应用程序设置为在卡片正面显示带有概念 definition/explanation 并在背面显示相应的 term/concept 的卡片。用户可以翻转卡片并通过单击按钮更改为另一张卡片。问题是目前,onClick 有时会显示之前显示的卡片。我想防止这种情况发生。我尝试使用三元运算符这样做,但不知何故,我的 Javascript 逻辑是错误的,因为我仍然得到重复显示。我该如何解决这个问题?
代码如下:
// data and components
import { conceptArray } from "./data";
import FlashCard from "./components/FlashCard";
function App() {
const [randomCard, setRandomCard] = useState({});
const [mode, setMode] = useState(true);
// this should store the individual concept (individual items in the concept Array) to later be displayed as a card
const getCard = () => {
// this changes the card and posits that there can be no repeat display of card that was displayed immediately before
let newCard = conceptArray[Math.floor(Math.random() * conceptArray.length)];
newCard !== randomCard ? setRandomCard(newCard) : newCard = conceptArray[Math.floor(Math.random() * conceptArray.length)];
// this allows for the front of the card(ie. the definition) to be displayed
setMode(true);
};
const flip = () => {
// this allows for the back of the card (ie. the term itself) to be displayed
setMode(!mode);
}
console.log(randomCard);
return (
<div className="App">
<header className="App-header">
<FlashCard randomCard={randomCard} mode={mode} />
<button onClick={getCard}>Get FlashCard</button>
<button onClick={flip}>Flip</button>
</header>
</div>
);
}
export default App;
如果您参考 this 关于 SOF 的问题,可以应用许多解决方案。 请检查这个函数,如果你需要随机数组,也许你可以全局使用它,只需传递数组长度
const generate_random_number = (_objLength) => {
let random_array_of_integers = [];
while (random_array_of_integers.length < _objLength) {
let random_integer = Math.floor(Math.random() * _objLength);
if (!random_array_of_integers.includes(random_integer))
random_array_of_integers.push(random_integer);
}
return random_array_of_integers;
}
所以我最终接受了将 conceptArray 改组为状态的建议。我使用 Fisher-Yates(又名 Knuth)Shuffle 这样做,可以在这里找到:How to randomize (shuffle) a JavaScript array?。我还不完全理解它背后的逻辑,但我能够将它应用到我的代码中并让它工作。现在,卡片以随机顺序抽取,不会立即重复。
正如 Thomas Wikman 如此简洁地解释的那样,这就像洗牌 conceptArray 中的项目,类似于洗牌的方式。一旦发生这种情况,我使用 onClick 从该数组中获取第一个项目,过滤掉数组以排除被获取的概念,然后继续获取另一个。完成数组中的最后一个概念后,我会再次执行随机播放并重新开始。
如果这对其他人有帮助,这里是结果代码:
// data and components
import { conceptArray } from "./data";
import FlashCard from "./components/FlashCard";
import AddForm from "./components/AddForm";
function App() {
// Fisher-Yates (aka Knuth) Shuffle
// don't completely understand it but I got it to work
const shuffle = array => {
var currentIndex = array.length, temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
// puts shuffled array of concepts into state
const [cardArray, setCardArray] = useState(shuffle(conceptArray));
const [randomCard, setRandomCard] = useState({});
const [frontMode, setFrontMode] = useState(true);
const [formMode, setFormMode] = useState(false);
// stores the individual concept (individual item in the concept Array) to be displayed as a card
const getCard = () => {
// grabs the first item in the shuffled array
setRandomCard(cardArray[0]);
// filters array so that item already displayed on card cannot be shown again until array is reshuffled
setCardArray(cardArray.filter(item => item !== cardArray[0]));
// when there is only one item left in filtered array, shuffles entire array again
if (cardArray.length === 1) {
setCardArray(shuffle(conceptArray));
}
// this allows for the front of the card(ie. the definition) to be displayed
setFrontMode(true);
};
const flip = () => {
// this allows for the back of the card (ie. the term itself) to be displayed
setFrontMode(!frontMode);
}
const renderForm = () => {
setFormMode(true);
}
// console.log(randomCard);
// console.log(conceptArrayRandomized);
// console.log(conceptArray);
return (
<div className="App">
{!formMode && <FlashCard randomCard={randomCard} frontMode={frontMode} />}
{!formMode && <button onClick={getCard}>Get FlashCard</button>}
{!formMode && <button onClick={flip}>Flip</button>}
<br />
{!formMode && <button onClick={renderForm}>Add New</button>}
{formMode && <AddForm />}
</div>
);
}
export default App;