Reputation: 511
The onCardLeftScreen event handler triggers the console log function but doesn't update state using the setState hook? I have tested that this is the issue with an onClick function which runs as intended.
React code:
//sets initial cards within the queue
const [cardQueue, setCardQueue] = useState([Data[0], Data[1], Data[2]]);
//sets the index of card that will be pushed into queue
const [cardQueueLength, setCardQueueLength] = useState(Data.length - 1);
const autoplayChange = () => {
setSlideShow(!slideShow);
console.log("playing!");
};
const CardLeftScreen = () => {
//iterates through cards(sets up loop)
setCardQueueLength(
cardQueueLength < Data.length - 1 ? cardQueueLength + 1 : 0
);
//removes card from front of queue
cardQueue.shift();
//pushes a card to back of queue
cardQueue.push(Data[cardQueueLength]);
//sets slideshow to true
setSlideShow(true);
//console logs cards in arrays and the index of the card being pushed to back of queue
console.log(cardQueue);
console.log(cardQueueLength);
};
return (
<div className="cardStyles">
{cardQueue.map((Projects, index) => {
return (
<TinderCard
key={Projects.workName}
preventSwipe={["up", "down"]}
onCardLeftScreen={CardLeftScreen}
className="Cards"
>
<Carousel
showThumbs={false}
infiniteLoop={true}
swipeable={false}
emulateTouch={false}
showStatus={false}
autoPlay={slideShow}
dynamicHeight={false}
>
<div className="image-iframeContainer">
{Projects.Images &&
Projects.Images.map((Image, index) => {
return (
<div key={Image} className="image-iframeContainer">
<img alt="Images of web apps" src={Image} />
</div>
);
})}
</div>
</Carousel>
<h1>{Projects.workName}</h1>
{Projects.workTech.map((Tech, index) => {
return (
<p key={Tech} className="techList">
{Tech}
</p>
);
})}
<div className="descriptionContainer">
<p className="description">{Projects.workDescription}</p>
</div>
</TinderCard>
);
})}
<button className='cardLeftScreenButton' onClick={CardLeftScreen}>click for onCardLeftScreen desired funtion</button>
</div>
);
I have also set up a Sandbox to better display my issue, Hopefully, someone can find a solution my project is so nearly finished. the API used is React-Tinder-Card
Upvotes: 2
Views: 85
Reputation: 511
The issue was caused due to the fact that the key used was not unique, the onClick function causes react to refresh updating the Dom whereas the onCardLeftScreen function doesn't by default. Setting the key of the Tindercard to key={Projects.workName + Math.random()}
fixes the issue as react knows when to refresh. Thanks, everyone for pointing out the state mutation it didn't fix my problem but certainly made my code cleaner
Upvotes: 1
Reputation: 870
Try something like this. You are mutating state directly which is not good and can lead to all sorts of side effects and mishaps, and maybe the reason you might see the same cards twice in a row, lag, etc.
// sets initial cards within the queue
const cards = [ Data[0], Data[1], Data[2] ];
const [cardQueue, setCardQueue] = useState(cards);
const [cardQueueLength, setCardQueueLength] = useState(Data.length - 1); //sets the index of card that will be pushed into queue
const autoplayChange = () => {
setSlideShow(!slideShow);
console.log("playing!");
};
//iterates through cards(sets up loop)
const handleCardLeave = () => {
const newCardQueueLength = cardQueueLength < Data.length - 1 ? cardQueueLength + 1 : 0;
setCardQueueLength(newCardQueueLength);
const updatedCardQueue = [...cardQueue]; // don't mutate state directly
updatedCardQueue.shift(); // removes card from front of queue
updatedCardQueue.push(Data[cardQueueLength]); // pushes a card to back of queue
setCardQueue(updatedCardQueue);
//sets slideshow to true
setSlideShow(true);
//console logs cards in arrays and the index of the card being pushed to back of queue
console.log(cardQueue);
console.log(cardQueueLength);
};
Upvotes: 1
Reputation: 26930
You are mutating your state array directly instead of duplicating it and affecting that array. This means that React doesn't think your array has actually changed. Consider the change below:
const {useState} = React;
const mockData = [
{title: "Foo", description: "Hello World!"},
{title: "Bar", description: "Fizz Buzz!"},
{title: "Cool", description: "More Stuff!"}
];
const MyComponent = () => {
const [cards, setCards] = useState([mockData[0], mockData[1], mockData[2]]);
const [nextDataIndex, setNextDataIndex] = useState(mockData.length - 1);
const onCardLeftScreen = () => {
const newNextDataIndex = nextDataIndex < mockData.length - 1 ? nextDataIndex + 1 : 0;
const newCards = [...cards];
newCards.shift();
newCards.push(mockData[newNextDataIndex]);
setNextDataIndex(newNextDataIndex);
setCards(newCards);
};
return (
<div>
<div>Num cards: {cards.length}</div>
<div className="card-container">
{cards.map(card => (
<div key={card.title} className="card">
<div>{card.title}</div>
<div>{card.description}</div>
</div>
))}
</div>
<button onClick={onCardLeftScreen}>Swipe Left</button>
</div>
);
};
const App = () => (
<MyComponent />
);
ReactDOM.render(
<App/>,
document.getElementById("app")
);
.card-container {
width: 100px;
height: 100px;
position: relative;
}
.card {
background-color: #0000AA;
color: #ffffff;
padding: 0.2em;
width: 50px;
height: 50px;
box-shadow: 2px 2px black;
position: absolute;
top: 0;
left: 0;
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="app"></div>
Upvotes: 1
Reputation: 153
whenever you set state in function it doesnt update immediately you can see the change only after event handler comes out of the function.
I think your code is correct and try console log after the function it will show you the intended result and if want to use the updated value use a variable like below
const CardLeftScreen = () => {
//iterates through cards(sets up loop)
let p=
cardQueueLength < Data.length - 1 ? cardQueueLength + 1 : 0
//removes card from front of queue
cardQueue.shift();
//pushes a card to back of queue
cardQueue.push(Data[p]);
//sets slideshow to true
setSlideShow(true);
setCardQueueLength(p);
//console logs cards in arrays and the index of the card being pushed to back of queue
console.log(cardQueue);
console.log(cardQueueLength);
};
console.log("you can see the change here",cardQueueLength);//you can see the change here
Upvotes: 1