Angular5中对象在同级兄弟组件间迁移及moves属性递减问题
Hey there! Let's work through fixing this component migration issue you're facing. The core problem here is that sibling components can't directly share state or update each other's data—we need to lift the shared state up to a parent component to handle the cross-component moves and moves counter updates.
Here's a step-by-step solution tailored to your setup:
First, let's assume you have a parent component that wraps both your Starters and Bench components. We'll move all shared state (player arrays and the moves counter) into this parent, then pass down data and callback functions to the siblings.
1. Parent Component (e.g., TeamManager.tsx)
This component will manage the source of truth for your players and move counter, and define the logic to transfer players between components:
import { useState } from 'react'; import Starters from './starters'; import Bench from './bench'; // Import your player type from your service file import { Player } from './path-to-your-service-file'; // Replace with your actual initial data fetch logic const getInitialStarters = () => [/* your starter players */]; const getInitialBench = () => [/* your bench players */]; const TeamManager = () => { const [starters, setStarters] = useState<Player[]>(getInitialStarters()); const [bench, setBench] = useState<Player[]>(getInitialBench()); const [moves, setMoves] = useState<number>(/* your initial moves value */); // Move a player from Starters to Bench const handleMoveToBench = (selectedPlayer: Player) => { if (moves <= 0) return; // Block moves when no attempts left // Update arrays immutably (critical for React state updates) setStarters(prev => prev.filter(player => player.id !== selectedPlayer.id)); setBench(prev => [...prev, selectedPlayer]); // Decrement moves counter setMoves(prev => prev - 1); }; // Move a player from Bench to Starters const handleMoveToStarters = (selectedPlayer: Player) => { if (moves <= 0) return; setBench(prev => prev.filter(player => player.id !== selectedPlayer.id)); setStarters(prev => [...prev, selectedPlayer]); setMoves(prev => prev - 1); }; return ( <div className="team-container"> <Starters players={starters} movesLeft={moves} onMoveToBench={handleMoveToBench} /> <Bench players={bench} movesLeft={moves} onMoveToStarters={handleMoveToStarters} /> </div> ); }; export default TeamManager;
2. Updated starters.ts Component
This component receives its data and move callback as props, and renders the move button for each player:
import { Player } from './path-to-your-service-file'; type StartersProps = { players: Player[]; movesLeft: number; onMoveToBench: (player: Player) => void; }; const Starters = ({ players, movesLeft, onMoveToBench }: StartersProps) => { const handleMove = (player: Player) => { if (movesLeft <= 0) { alert('No moves remaining!'); return; } onMoveToBench(player); }; return ( <div> <h2>Starters</h2> <p>Remaining Moves: {movesLeft}</p> <ul> {players.map(player => ( <li key={player.id}> {player.name} {/* Replace with your player display logic */} <button onClick={() => handleMove(player)} disabled={movesLeft <= 0} > Move to Bench </button> </li> ))} </ul> </div> ); }; export default Starters;
3. Updated bench.ts Component
Mirror the starters component logic for moving players back to starters:
import { Player } from './path-to-your-service-file'; type BenchProps = { players: Player[]; movesLeft: number; onMoveToStarters: (player: Player) => void; }; const Bench = ({ players, movesLeft, onMoveToStarters }: BenchProps) => { const handleMove = (player: Player) => { if (movesLeft <= 0) { alert('No moves remaining!'); return; } onMoveToStarters(player); }; return ( <div> <h2>Bench</h2> <p>Remaining Moves: {movesLeft}</p> <ul> {players.map(player => ( <li key={player.id}> {player.name} <button onClick={() => handleMove(player)} disabled={movesLeft <= 0} > Move to Starters </button> </li> ))} </ul> </div> ); }; export default Bench;
Key Fixes & Explanations:
- State Lifting: By moving the player arrays and
movescounter to the parent, we ensure both sibling components always have access to the latest, synchronized data. - Immutable State Updates: We use
filterand the spread operator ([...prev]) to create new arrays instead of modifying the original ones. This lets React detect state changes and re-render components correctly. - Controlled Moves: We check if
moves > 0before allowing any transfers, and disable buttons when no moves are left to prevent invalid actions.
内容的提问来源于stack exchange,提问作者LDB

