0

I'm working on a Tinder-like app and trying to remove the current card from the array and move on to the next when clicking either the like or dislike button. Simultaneously, I am trying to add the card to a new array (list of liked or disliked). Adding the object to new array seems to work (although there's a delay and the button needs clicked twice - which also needs to be sorted), but as soon as I try to remove it from the current array it all crashes.

I tried looking at this solution: Removing object from array using hooks (useState) but I only ever get "TypeError: Cannot read property 'target' of undefined" no matter what I try. What am I missing?

This is the code:

import React, { useState, useEffect } from 'react';
import { Card, Button, Container } from 'react-bootstrap';

const url = 'https://swiperish-app.com/cards';

const SwiperCard = () => {
  const [cardData, setCardData] = useState([]);
  const [likedItem, setLikedItem] = useState([]);


  useEffect(() => {
    fetch(url)
      .then(res => res.json())
      .then(cardData => setCardData(cardData))
  });

  const handleRemoveItem = (event) => {
    const name = event.target.getAttribute("name")
    setCardData(cardData.filter(item => item.id !==name));  
  };

  const likedCards = (itemId, itemImg, ItemTitle) => {
    let likedArr = [...likedItem];
    setLikedItem(likedItem => likedItem.concat({itemId, itemImg, ItemTitle}))
    handleRemoveItem();
    console.log(likedArr);
  };

  return (
      <div id="contentView">
        {cardData.map((item, index) => {
          return(
            <Card key={index} className="cardContainer" name={item.id}>
              <Container className="btnContainer">
                <div className="btnWrapper">
                  <Button className="btn" onClick={() => console.log(item.id)}>DISLIKE</Button>
                </div>
              </Container>
              <Container className="cardContentContainer">
                <Card.Img style={{width: "18rem"}}
                  variant="top" 
                  src={item.image} 
                  fluid="true" 
                />
                <Card.Body style={{width: "18rem"}}>
                  <Card.Title className="cardTitle">{item.title.toUpperCase()}</Card.Title>
                  <Card.Subtitle className="cardText">{item.body}</Card.Subtitle>
                </Card.Body>
              </Container>
              <Container className="btnContainer">
                <div className="btnWrapper">
                  <Button className="btn" onClick={() => likedCards(item.id, item.image,item.title) }>LIKE</Button>
                </div>
              </Container>
            </Card>
          )
        })}
      </div>
  );
};

export default SwiperCard;

2 Answers 2

1

You can move cards between two arrays with

 const likedCards = (item) => {
    setLikedItem([...likedItem, item]);
    let filtered = cardData.filter((card) => card.itemId !== item.itemId);
    setCardData(filtered);
  };

I suggest you to add empty array as second parameter of useEffect,since you are using as componentDidMount.

As second suggestion you can setLoading true before fetch and setLoading false after to reduce errors in render.

Sign up to request clarification or add additional context in comments.

4 Comments

Sorry, I'm still a little lost... surely you can't assign a new value to cardData in that way since it's a constant?
Sorry for confusion :) I updated the solution dont forget to pass whole item object into function
Now all the cards disappeared at once instead of one at a time, and likedCards is empty according to the console log. So sorry, but clearly I'm dire in need of getting this explained to me like I'm a 5 year old.
@BBHeX I hope this works for you, I also added back button codesandbox.io/s/…
0

You're calling handleRemoveItem with no arguments, but that function is doing something with an event parameter, so you're going to get a TypeError.

It seems like handleRemoveItem really only needs to know about the item ID to remove, so you can simplify to:

const removeCard = id => {
  setCardData(cardData.filter(item => item.id !== id));
};

const handleLike = (itemId, itemImg, ItemTitle) => {
  setLikedItem([...likedItem, {itemId, itemImg, ItemTitle}]);
  removeCard(itemId);
};

I also noticed that you're sometimes logging a state variable immediately after calling the setting. That won't work. It's not until the next call to useState on the next render when you'll receive the value, so if you want to log changes to state, I'd log in your render function, not in an event handler.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.