React记忆游戏开发求助:4×4布局与新游戏重置功能实现
Hey there! Let's tackle your two issues one by one, and I'll explain the logic behind each fix so you understand what's going on.
1. Fixing the 4×4 Card Layout
Right now, your cards are probably rendering in a single row/column because the parent .game container lacks layout styling. The simplest way to get a clean 4×4 grid is using CSS Grid—it’s built exactly for this kind of two-dimensional layout.
Add this CSS to your stylesheet:
.game { display: grid; grid-template-columns: repeat(4, 1fr); /* Creates 4 equal-width columns */ gap: 1rem; /* Adds space between cards for better readability */ max-width: 600px; /* Optional: Prevents cards from stretching too wide */ margin: 2rem auto; /* Optional: Centers the grid on the page */ }
What each line does:
display: grid: Turns the.gamediv into a grid container, enabling grid layout for its children.grid-template-columns: repeat(4, 1fr): Creates 4 columns where each takes an equal fraction of the available space (1fr). This keeps the layout responsive across screen sizes.gap: Adds consistent spacing between rows and columns—adjust the value to match your design preferences.
2. Implementing the New Game Button
Your start method currently modifies state directly (which React doesn’t allow—state should only be updated via setState()), and the button isn’t connected to any function. Let’s fix both issues:
Step 1: Rewrite the start method to use setState correctly
// Convert to an arrow function to avoid `this` binding problems start = () => { // Create a duplicated array (8 original + 8 copies = 16 total cards) const duplicatedFrameworks = [...this.state.frameworks, ...this.state.frameworks]; // Shuffle the duplicated array const randomizedFrameworks = this.shuffle(duplicatedFrameworks); // Map to the finalized card structure with initial states const finalizedFrameworks = randomizedFrameworks.map(name => ({ name, close: true, complete: false, fail: false })); // Update state properly (this triggers a re-render) this.setState({ finalizedFrameworks, openedFrameworks: [] // Reset any opened cards for the new game }); };
Key fixes here:
- We use spread syntax (
[...array]) to create copies of state arrays instead of mutating the original state (React relies on immutable state updates to detect changes). - The arrow function for
startensuresthisrefers to the component instance, so you don’t need to bind it in the constructor. - We reset
openedFrameworksto an empty array to clear any previously flipped cards when starting a new game.
Step 2: Wire up the button in your render method
Update the button to call the start function when clicked:
<button onClick={this.start}> NEW GAME </button>
Bonus: Initialize the game on component mount
Make sure your constructor initializes state and starts the game when the component first loads:
constructor(props) { super(props); this.state = { frameworks: ['React', 'Vue', 'Angular', 'Svelte', 'Next.js', 'Nuxt.js', 'Gatsby', 'Remix'], // Your 8 unique framework names finalizedFrameworks: [], openedFrameworks: [] }; // Start the game immediately when the component mounts this.start(); }
With these changes, your cards will render in a clean 4×4 grid, and clicking the "NEW GAME" button will reshuffle the cards and reset all game states.
内容的提问来源于stack exchange,提问作者Elemke

