Reputation: 291
I'm trying to build this memory game, for now, my code renders a series of pokemon names with a button and each time you click a button, the name of the pokemon is stored inside an array. But for now, the duplicate ones also get pushed, meaning that you can click twice the same button and the value will still be pushed to the array. I wwould like that only one item name gets pushed and if it is pressed another time for it to perform another action. Is there anyway to do this?
I've tried making an useEffect with include method but it is not working...
Code I've tried to run:
useEffect(() => {
clicked.map(item => {
if (item.includes(item)) {
console.log("hello")
}
}
)
}, [clicked] )
Full code of my program:
import React, {useState, useEffect} from 'react'
function Cards() {
const [items, setItems] = useState([])
const [clicked, setClicked] = useState([])
useEffect(() => {
fetch("https://pokeapi.co/api/v2/pokemon/?limit=12")
.then((res) => res.json())
.then(({ results }) => {
setItems(results);
});
}, []);
useEffect(() => console.log(clicked), [clicked]);
useEffect(() => {
clicked.map(item => {
if (item.includes(item)) {
console.log("hello")
}
}
)
}, [clicked] )
const pushPokemon = (e) => {
var pokemon = e.target.innerHTML
setClicked([...clicked, pokemon])
}
return (
<div>
{items.map(item => (
<button onClick={pushPokemon}>{item.name}</button>
))}
</div>
)
}
export default Cards
Upvotes: 0
Views: 111
Reputation: 36
You need to add a check while setting clicked by using includes() function and logging to check for repeated clicked items can be improved. I have changed logging function and pushPokemon function. Working demo as follows:
import React, { useState, useEffect } from "react";
function Cards() {
const [items, setItems] = useState([]);
const [clicked, setClicked] = useState([]);
useEffect(() => {
fetch("https://pokeapi.co/api/v2/pokemon/?limit=12")
.then((res) => res.json())
.then(({ results }) => {
setItems(results);
});
}, []);
useEffect(() => {
console.log(clicked);
});
const pushPokemon = (e) => {
var pokemon = e.target.innerHTML;
if(!clicked.includes(pokemon)) {
setClicked([...clicked, pokemon]);
} else {
console.log('Repeated item clicked!')
}
};
return (
<div>
{items.map((item) => (
<button onClick={pushPokemon}>{item.name}</button>
))}
</div>
);
}
export default Cards;
Upvotes: 2
Reputation: 35684
you might want to differentiate between the buttons and the values, since in the memory game I assume two different buttons would have the same values.
const [buttons, setButtons] = useState([])
// ...
const pushPokemon = (e) => {
const btn = e.target
// if button already included, return
if (buttons.includes(btn)) return;
// add button to array
setButtons([...buttons, btn])
var pokemon = e.target.innerHTML
setClicked([...clicked, pokemon])
}
Upvotes: 0
Reputation: 231
I would suggest not using innerHTML and instead just passing the name of the pokemon you are trying to add to pushPokemon
. Also in your example you would add the pokemon for a second time before your useEffect
on clicked
runs to detect the duplicate. For this reason I think what you want is to check for the duplicates in the pushPokemon
function itself.
import React, {useState, useEffect} from 'react'
function Cards() {
const [items, setItems] = useState([])
const [clicked, setClicked] = useState([])
useEffect(() => {
fetch("https://pokeapi.co/api/v2/pokemon/?limit=12")
.then((res) => res.json())
.then(({ results }) => {
setItems(results);
});
}, []);
const pushPokemon = (pokemon) => {
const isDuplicate = clicked.includes(pokemon);
if (isDuplicate) {
// If we have already added this pokemon, return before adding again to the list
return console.log("You already selected ", pokemon);
}
// Else, this pokemon has not been clicked, so add it to state
setClicked([...clicked, pokemon])
}
return (
<div>
{items.map(item => (
<button onClick={() => pushPokemon(item.name)}>{item.name}</button>
))}
<div>{JSON.stringify(clicked)}</div>
</div>
)
}
export default Cards
Upvotes: 1
Reputation: 649
Not a very good approach but you can try this:
const pushPokemon = (e) => {
var pokemon = e.target.innerHTML
if(!clicked.find(x=> x === pokemon))
{
setClicked([...clicked, pokemon])
}
}
So, it will find if the item exists and shall run only if it isn't there.
Upvotes: 0