It is supposed to execute only the function shuffleCards
when I click the button but instead it also executes the two console.log()
statements, the one before and after the function.
Why is this happening?
The code:
import { useState } from 'react';
const cardImages = [
{"text": "A"},
{"text": "B"},
{"text": "C"},
{"text": "D"},
{"text": "E"},
{"text": "F"},
]
function App() {
const [cards, setCards] = useState([]);
const [turns, setTurns] = useState(0);
console.log("Cardssssssssss")
const shuffleCards = () => {
const shuffledCards = [...cardImages, ...cardImages]
.sort(() => Math.random() - 0.5)
.map((card) => ({ ...card, id: Math.random() }))
setCards(shuffledCards);
setTurns(0) // understand sort() method
} // even though rahom bara lfunction rahom y'atfficha f onclick why
console.log("Cards:", cards)
return (
<div className="App text-center p-4 text-white bg-[black] h-[100vh] " >
<h1 className='text-4xl font-bold ' >Magic Match</h1>
<button
onClick={shuffleCards}
className='border-white border border-solid p-1 px-2 mt-4 '
>
New Game
</button>
</div
CodePudding user response:
In react when a component render, all the functions before the return
are executed, so you are calling shuffleCards() onClick but before all the code
between function App() {
and return (
got executed,
btw replace onClick={shuffleCards}
by onClick={ () => { shuffleCards() } }
to call in only when click !
CodePudding user response:
Both console logs are in the component body and the entire function body of a React function component is the "render" function. These logs are unintentional side-effects.
You will see both logs occur any time the component renders for any reason at all.
In this specific case when the button is clicked and the shuffleCards
callback handler is invoked, it enqueues two state updates to cards
and turns
which will trigger a component rerender after they are processed.
Generally you will want to place side-effects into the very appropriately named useEffect
hook.
Example:
function App() {
const [cards, setCards] = useState([]);
const [turns, setTurns] = useState(0);
useEffect(() => {
console.log("Cardssssssssss");
}, []); // <-- empty dependency, runs once on component mount
const shuffleCards = () => {
const shuffledCards = [...cardImages, ...cardImages]
.sort(() => Math.random() - 0.5)
.map((card) => ({ ...card, id: Math.random() }));
setCards(shuffledCards);
setTurns(0);
};
useEffect(() => {
console.log("Cards:", cards);
}, [cards]); // <-- cards dependency, run effect when cards updates
return (
<div className="App text-center p-4 text-white bg-[black] h-[100vh] " >
<h1 className='text-4xl font-bold ' >Magic Match</h1>
<button
onClick={shuffleCards}
className='border-white border border-solid p-1 px-2 mt-4 '
>
New Game
</button>
</div