在映射React中的某些组件时,如何更改它们的可见性



在不使前提过于复杂的情况下,我试图在React中构建一个文字游戏,该游戏通过组件进行映射,并根据组件在循环中的渲染时间来更改其可见性。这是我第一次尝试在React中构建游戏,所以我提前为我普遍缺乏理解而道歉。我能够在普通JavaScript中构建相同的逻辑,但在React中,当涉及到针对组件并根据它们所拥有的数据更改它们的状态时,我仍然非常困惑。

在我的游戏中,我试图渲染一个8x9列的网格,每列高9个值,每行宽8个值。然而,在最初加载游戏时,我只希望前三行组件可见。目标是让更多的组件在设置超时函数的基础上随时间渲染,但这是以后的问题。我习惯于思考这个问题的方法是映射一个值数组,对非null的值执行X操作,对null的值进行Y操作。因此,我编写了这样的组件:

const Letter = ({ letter }) => {
// This component takes in a random letter and sends the letter to a form input element when clicked
const [clicked, setClicked] = useState(false);
const [currLetter, setCurrLetter] = useState('');
const { inputVal, setInputVal} = useInputContext();
useEffect(() => {
const currValues = [];

if (clicked) currValues.push(`${currLetter}`)
setInputVal(inputVal.concat(currValues))
}, [clicked])
return <div className='letters' disabled={clicked} onClick={() => {
setClicked((clicked) => !clicked);
setCurrLetter(`${letter}`)
}}>{letter}</div>
};
export default Letter;

下一个组件

const Column = () => {
const [randomCol, setRandomCol] = useState([]);
const vowels = ['A', 'E', 'I', 'O', 'U', 'Y'];
const consonants = ['B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'V', 'W']
const goldConsonants = ['X', 'Z', 'Q'];
const randomGen = Math.floor(Math.random() * 100);
const letterGenerator = () => {
// Generates a random letter that letter gets passed into my letter component
const randomNum = randomGen;
if (randomNum >= 40) return consonants[Math.floor((Math.random()*consonants.length))];
if (randomNum >= 5 && randomNum < 40) return vowels[Math.floor((Math.random()*vowels.length))];
return goldConsonants[Math.floor((Math.random()*goldConsonants.length))];
};
useEffect(() => {
const col = [];
// Renders the letter components
for (let j = 0; j < 9; j++) {
// These last three values in my columns should be visible (last three rows)
if (j >= 6) col.push(<Letter letter={letterGenerator()} key={j} />)
/* These components should not be visible. I have attempted inline styling
as well as giving them an id and targeting them in a separate CSS file,
to no avail */
if (j < 6) col.push(<Letter style={{ visibility: 'hidden' }} id='null' key={j}  />)
};
setRandomCol(col);
}, []);
return (
<div className='columns'>
{randomCol.map(val => val)}
</div>
);
};
export default Column;

下一个组件

const Board = () => {
// Pushes the columns into an array and maps through them
const board = []
for (let i = 0; i < 8; i++) {
board.push(<Column key={i} />)
};
return (
<div className='main-board'>
{board.map(col => col)}
</div>
);
};
export default Board;

所有这些都很好,减去特定字母组件的条件"可见性"样式。根据游戏机制,我需要能够将更多的字母呈现为"null",并在未来基于用户交互将其从棋盘视图中删除。到目前为止,我还没有特别关注这一方面,但如果能朝着的正确方向推动如何开始思考这个问题,我将不胜感激。

这个问题似乎主要是关于Column组件的。将style道具传递给Letter是不起作用的,除非同时将其传递给某个DOMNode,即div

在React中,将JSX存储在状态中是反模式的。您应该将数据存储为状态,并将状态映射到要呈现的JSX。

重构示例:

const vowels = ['A', 'E', 'I', 'O', 'U', 'Y'];
const consonants = [
'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L',
'M', 'N', 'P', 'R', 'S', 'T', 'V', 'W'
];
const goldConsonants = ['X', 'Z', 'Q'];
const randomGen = () => Math.floor(Math.random() * 100);
const letterGenerator = () => {
// Generates a random letter that letter gets passed into my letter component
const randomNum = randomGen();
if (randomNum >= 40) {
return consonants[Math.floor((Math.random() * consonants.length))];
} else if (randomNum >= 5 && randomNum < 40) {
return vowels[Math.floor((Math.random() * vowels.length))];
}
return goldConsonants[Math.floor((Math.random() * goldConsonants.length))];
};
const Column = () => {
// Generate an array of 9 random letters
const [randomCol, setRandomCol] = useState(() => {
return Array.from({ length: 9 }, letterGenerator);
});

return (
<div className='columns'>
{randomCol.map((letter, i) => ( // <-- map letters to Letter components
<Letter key={i} letter={letter} hidden={i < 6} />
))}
</div>
);
};

Letter组件中,使用传递的hidden道具有条件地将类名或style道具值应用于。

// This component takes in a random letter and sends the
// letter to a form input element when clicked
const Letter = ({ hidden, letter }) => {
...
return (
<div
className={
[
'letters',
hidden ? "hidden" : null // conditionally apply class
]
.filter(Boolean)
.join(" ")
}
disabled={clicked}
onClick={() => {
setClicked((clicked) => !clicked);
setCurrLetter(letter);
}}
>
{letter}
</div>
);
};

.hidden {
visibility: hidden;
}

相关内容

  • 没有找到相关文章

最新更新