I am seeing some strange behaviour when I am trying to pass down a variable to a child component in react. When I console.log just before the return statement (so console.log(1)) in the parent component the data is correct, however when I console.log in the child component (so console.log(2)) the data has changed??
I have a suspicion that it relates to the randomSelect() function but again when console logging out this looks to only be called twice (as expected).
I have pasted a 'playerOneId' in directly (avoiding using the randomSelect() function) and the data shows correctly in the child component when doing this, hence my suspicion around the randomSelect() function. It could be unrelated but not sure.
A gold medal to anyone can answer this one as it has had me for hours now and I've run out of ideas.
PARENT COMPONENT:
const Board = () => {
const [starships, setStarships] = useState([]);
const [playerSelected, setPlayerSelected] = useState(false);
const [result, setResult] = useState('');
const [playerScore, setPlayerScore] = useState(0);
const [computerScore, setComputerScore] = useState(0);
const STARSHIP_QUERY = `{
allStarships {
starships {
id
name
starshipClass
maxAtmospheringSpeed
costInCredits
passengers
filmConnection {
films {
title
}
}
}
}
}
`
useEffect(() => {
fetch('https://connectr-swapi.herokuapp.com/', {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({query: STARSHIP_QUERY})
})
.then(response => response.json())
.then(data => setStarships(data.data.allStarships.starships))
.catch(error => console.log({'Error': error}))
},[])
const randomSelect = () => {
const random = Math.floor(Math.random() * starShipIds.length);
const selectedId = starShipIds[random];
return selectedId;
}
const starShipIds = starships.map(ship => ship.id)
const valueOneID = randomSelect();
const valueTwoID = randomSelect();
const playerOneId = valueOneID;
const computerId = valueTwoID;
const playerOneShip = starships.filter(ship => ship.id === playerOneId) ;
const computerShip = starships.filter(ship => ship.id === computerId);
const catergorySelect = (key, value) => {
let computerValue = key === 'filmConnection' ? computerShip[0][key].films.length : computerShip[0][key];
if (value > computerValue) {
setResult('You Win!');
setPlayerScore(playerScore + 1)
}
if (value === computerValue) setResult('You Draw!');
if (value < computerValue) {
setResult('You Lose!');
setComputerScore(computerScore + 1)
}
setPlayerSelected(true);
}
console.log(1, playerOneShip[0]); // data is showing correctly
return (
<div className="background">
<div className="row">
<div className="col-12 col-sm-4">
{playerOneShip.length &&
<GameCard
ship={playerOneShip[0]} // data passed in
player='player-one'
select={catergorySelect}
/>
}
{playerSelected &&
<Score
score={playerScore}
colour="white"
/>
}
</div>
<div className="col-12 col-sm-4">
<div className="row">
<h1>{result}</h1>
</div>
<div className="row">
<DefaultBtn
text="START AGAIN"
colour="white"
/>
</div>
</div>
<div className="col-12 col-sm-4">
{playerSelected &&
<React.Fragment>
<div>
{computerShip.length &&
<GameCard
ship={computerShip[0]}
player='computer'
catergorySelect={catergorySelect}
/>
}
</div>
<div>
<Score
score={computerScore}
colour="white"
/>
</div>
</React.Fragment>
}
</div>
</div>
</div>
)
}
CHILD COMPONENT:
const GameCard = props => {
const [selected, setSelected] = useState(0);
const [disableCategory, setDisableCategory] = useState(false);
const {
ship,
player,
select,
} = props;
console.log(2, ship) // different data is showing
const categories = Object.entries(props.ship).map(([key, value], index) => {
const choosenCategory = selected === index ? 'selected' : '';
const disableButton = disableCategory ? 'disable' : '';
switch (key) {
case 'maxAtmospheringSpeed':
return <li className={`card ${player} ${choosenCategory} ${disableButton}`} onClick={(() => { select(key, value); setSelected(index); setDisableCategory(true)})} key={index}>{`Maximum Speed: ${value}`}</li>
case 'costInCredits':
return <li className={`card ${player} ${choosenCategory} ${disableButton}`} onClick={(() => { select(key, value); setSelected(index); setDisableCategory(true)})} key={index}>{`Cost In Credits: ${value}`}</li>
case 'passengers':
return <li className={`card ${player} ${choosenCategory} ${disableButton}`} onClick={(() => { select(key, value); setSelected(index); setDisableCategory(true)})} key={index}>{`Number Of Passengers: ${value}`}</li>
case 'filmConnection':
return <li className={`card ${player} ${choosenCategory} ${disableButton}`} onClick={(() => { select(key, value.films.length); setSelected(index); setDisableCategory(true)})} key={index}>{`Number Of films: ${value.films.length}`}</li>
default:
return null
}
});
return (
<div className="card">
<img className="card-image" src="assets/img/starships/2.jpg" />
<div className="card-body">
<p className="card-title">{`Ship Name: ${ship.name}`}</p>
<p className="card-sub-title">{`Class: ${ship.starshipClass}`}</p>
<ul>
{categories}
</ul>
</div>
</div>
)
}