0

I have set up my project in the style of tinder cards I would like users to be able to swipe through the cards and have the card swiped removed so the card next in the array can be added to the but I'd also like this to infinitely loop through the array with a maximum limit of 3 cards displayed at a time. So far I have tried using the splice and slice functions, here I and trying to iterate through sections of the array 3 at a time but it doesn't seem to work what are the suggestions?

This is the reactjs code I have written so far:

import React, { useState, useEffect } from 'react';
import Data from '../Data/webApps_data';
import TinderCard from 'react-tinder-card';
import "react-responsive-carousel/lib/styles/carousel.min.css"; // requires a loader
import { Carousel } from 'react-responsive-carousel';
import ReactPlayer from 'react-player/youtube'

function Webapps() {

    let [cardController_end, setCardController_end] = useState(3);
    let [cardController_start, setCardController_start] = useState(0);

    const onCardLeftScreen = (Project_card) => {
        console.log(Project_card + ' left the screen')
        setCardController_end(cardController_end < Data.length ? cardController_end + 1 : 0)
        setCardController_start(cardController_start < Data.length ? cardController_start + 1 : 0)
    }

    return (
        <div className='cardStyles'>
                {Data.slice(cardController_start, cardController_end).map((Projects, index) => {
                    return <TinderCard key={Projects.workName} onCardLeftScreen={() => onCardLeftScreen(Projects.workName)} className='Cards'>
                        <Carousel>
                            {Projects.Images && Projects.Images.map((Image, index) => { return <div key={Image} className='image-iframeContainer'><img alt='Images of web apps' src={require("../assets/Port-images/Web-Apps/" + Image)} /></div> })}
                            {Projects.videoAddress && Projects.videoAddress.map((Video, index) => { return <div key={Video} className='image-iframeContainer'><ReactPlayer url={Video} muted={false} controls={false} onPlay={autoplayChange} onPause={autoplayChange} onEnded={autoplayChange} /></div> })}
                        </Carousel>
                        {Projects.webAddress && <div className='webButton'><LinkIcon onClick={() => { window.open(Projects.webAddress); }} /></div>}
                        <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>
                })}
        </div >
    )
}

export default Webapps;

Here's an example of the JSON array used:

//Webs and apps component data
export default[

    {
        workName: 'The life of ACD',
        workDescription: 'This was developed while working for the Arthur Conan Doyle foundation based in Portsmouth. Its is a maps base app which shows the life events of Arthur Conan Doyle(Author of the Sherlock Holmes books) within portsmouth.',
        workTech: ['React.js, HTML, Sass, OpenStreetMap API, node.js'],
        videoAddress: ['https://www.youtube.com/watch?v=lV9Hv05uB54'],
        webAddress: 'https://arthur-conan.netlify.app/Map',
        Images: ['ACD1.jpg', 'ACD2.jpg', 'ACD3.jpg', 'ACD4.jpg']
    },

    {
        workName: 'HistoryLens',
        workDescription: 'HistoryLens is an educational history web site taking inspiration from sites such as BBC history. It was developed with a friend as part of a group project at university.',
        workTech: ['Bootstrap, PHP, Css, Javascript'],
        videoAddress: ['https://www.youtube.com/watch?v=oUimrYIhxLA'],
        webAddress: '',
        Images: ['History1.png', 'History2.png', 'History3.png', 'History4.png', 'History5.png']
    },

    {

        workName: 'Simplyfit',
        workDescription: 'Simplyfit is a mobile app developed with the intention of helping people create tailor made meal plans. The app was developed for my final year project at university.',
        workTech: ['React.js, HTML, Sass, Material-ui, Firebase, Firestore, node.js'],
        videoAddress: ['https://www.youtube.com/watch?v=-zuxYPJrlmw'],
        webAddress: 'https://simplyfit.netlify.app/',
        Images: ['Simplyfit1.jpg', 'Simplyfit2.jpg', 'Simplyfit3.jpg', 'Simplyfit4.jpg', 'Simplyfit5.jpg']
    },

    {
        workName: 'Dirty Pint',
        workDescription: 'Dirty Pint is a fun drinking game where players can enter in a drink of their choice and disgusting mixer is displayed along with a pun.',
        workTech: ['PhoneGapp, HTML, Css, Bootstrap, Javascript'],
        videoAddress: ['https://www.youtube.com/watch?v=TLEVkopN1Xk'],
        webAddress: '',
        Images: ['Dirty1.jpg', 'Dirty2.jpg', 'Dirty3.jpg', 'Dirty4.jpg']
    },

]

edit: I've also added some Sass that means each array item printed has -1 z-index from the previous card before thought I'd say in case it causes confusion.

Edit using javascript queue function

let [cardQueue, setCardQueue] = useState([Data[0], Data[1], Data[2]]);
let [cardQueueLength, setCardQueueLength] = useState(2)

const onCardLeftScreen = (Project_card) => {
    console.log(Project_card + ' left the screen');
    cardQueue.shift();
    setCardQueueLength(cardQueueLength < Data.length ? cardQueueLength + 1 : 0)
    cardQueue.push(Data[cardQueueLength]);

}


return (
    <div className='cardStyles'>
            {cardQueue.map((Projects, index) => {
                return <TinderCard key={Projects.workName} preventSwipe={['up', 'down']} onCardLeftScreen={() => onCardLeftScreen(Projects.workName)} className='Cards'>
                    <Carousel>
                        {Projects.Images && Projects.Images.map((Image, index) => { return <div key={Image} className='image-iframeContainer'><img alt='Images of web apps' src={require("../assets/Port-images/Web-Apps/" + Image)} /></div> })}
                        {Projects.videoAddress && Projects.videoAddress.map((Video, index) => { return <div key={Video} className='image-iframeContainer'><ReactPlayer url={Video} muted={false} controls={false} onPlay={autoplayChange} onPause={autoplayChange} onEnded={autoplayChange} /></div> })}
                    </Carousel>
                    {Projects.webAddress && <div className='webButton'><LinkIcon onClick={() => { window.open(Projects.webAddress); }} /></div>}
                    <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>
            })}
        </div>
)
}

export default Webapps;

this isn't working but seems the best approach to me is my implementation of the queue correct? i tried to push using the 'set' hook to no avail?

new thread Really struggling with why this isn't working made a new thread addressing the issues with push and shift.

lukeet
  • 461
  • 1
  • 4
  • 22

3 Answers3

1

You should create a queue of the items and then page them accordingly. Here's a post I used for example of creating queue.

How do you implement a Stack and a Queue in JavaScript?

billy_comic
  • 867
  • 6
  • 27
  • In the example shared which part would be my data? the stack? then would i pass the index values into a queue? I'm not sure I quite understand – lukeet Sep 25 '20 at 13:21
  • I'm reading through the documentation will mark if works! thanks – lukeet Sep 25 '20 at 13:34
  • Hi I've tried to implement your solution but it only appears to work for the first card? I'll post it as an edit seems the best solution it could be my implemtation – lukeet Sep 25 '20 at 14:03
  • I've updated the post using your suggestion if you wouldn't mind taking a look at my implementation :) – lukeet Sep 25 '20 at 14:09
  • This is the answer the my implimentation is correct the problem was with the library see here in the sandbox https://codesandbox.io/s/wandering-firefly-nxqv7 – lukeet Sep 26 '20 at 15:14
  • 1
    While our use cases are different, I think you are heading down the right track. This should always keep track of all of the "cards" in memory and allow you to cycle them in order infinitely. – billy_comic Sep 28 '20 at 14:38
0

.slice faster than .filter

The filter method is clean, but loop through every item in the array at least once.

let myArrayData = [
  {
    id: 1,
    name: "A"
  },
  {
    id: 2,
    name: "B"
  },
  {
    id: 3,
    name: "C"
  },
  {
    id: 4,
    name: "D"
  }
];

// with .slice
let dataSlice = myArrayData.slice(0, 2).map((item) => {
      console.log("item", item.name)  
      return item
    });


console.log( "dataSlice ", dataSlice  );

// with .filter
let dataFilter = myArrayData.filter((item, idx) => idx < 2).map(item => {
    console.log("item", item.name)
    return item
});

console.log("dataFilter ", dataFilter );
GMKHussain
  • 3,342
  • 1
  • 21
  • 19
-1

Depending on the index you can return the thing you want to display or just null.

let maxDisplay = 5;
youArray.map((row, index) => {
   if(index < maxDisplay){
     return <div>...</div>
   }else{
     return null
   }
});

Warning: don't use the results for other things than display, because you'll have an array with "null" values in it.

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
Maxime Girou
  • 1,511
  • 2
  • 16
  • 32
  • I don't understand how this will help me iterate and loop through my array data? all that appears to do to me is set the max value of divs printed to 5 which I could have done with a simple youArray.slice(0, 5).map() am I wrong? – lukeet Sep 25 '20 at 13:27
  • You could have a startIndex and endIndex and based on them, render the components for values that are falling between them. So in your case, it seems to be carController_start and cardController_end – szczocik Sep 25 '20 at 13:46
  • I'm trying the javascript queue funtion with push() and shift() are you familiar? – lukeet Sep 25 '20 at 14:13
  • @lukeet i didn't undestrand well your question, i understoof that you wanna use .map function and display a limited number of element. i show you how. – Maxime Girou Sep 25 '20 at 18:54