0

I'm trying to change the state of "show" in a specific card component onPress. onPress I filter to get the object and set the value of show to true. When I console log the changed array, I can see the change but when I setState, I get error "TypeError: Cannot read property 'show' of undefined"

I think the problem is that when I initialize the app, I splice from "cards" (this is so I don't copy repeats) and setState renders the CardBox component (and "cards" is empty), not just Card. Can anyone point me towards the right direction of fixing this.

export default class CardBox extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      selected_cards: [],
      rnd_card_list: [],

      cards: [
        {
          id: 1,
          name: "star",
          color: "#ffeaa5",
          show: false
        },
        {
          id: 2,
          name: "heart",
          color: "#f3c1c6",
          show: false
        },
        {
          id: 3,
          name: "headphones",
          color: "#f58b54",
          show: false
        },
        {
          id: 4,
          name: "bell-o",
          color: "#107595",
          show: false
        },
        {
          id: 5,
          name: "video-camera",
          color: "#ff0b55",
          show: false
        },
        {
          id: 6,
          name: "pencil",
          color: "#a34a28",
          show: false
        },
        {
          id: 7,
          name: "star",
          color: "#ffeaa5",
          show: false
        },
        {
          id: 8,
          name: "heart",
          color: "#f3c1c6",
          show: false
        },
        {
          id: 9,
          name: "headphones",
          color: "#f58b54",
          show: false
        },
        {
          id: 10,
          name: "bell-o",
          color: "#107595",
          show: false
        },
        {
          id: 11,
          name: "video-camera",
          color: "#ff0b55",
          show: false
        },
        {
          id: 12,
          name: "pencil",
          color: "#a34a28",
          show: false
        }
      ]
    };
  }

  handlePress = s_card => {
    let rnd_list = this.state.rnd_card_list;
    let x = rnd_list.indexOf(s_card);

    var sCard = rnd_list.filter(card => card.id === s_card.id);
    sCard[0].show = true;

    rnd_list[x] = sCard[0];

    this.setState({ rnd_list });

    // if (this.state.selected_cards.length === 2) {
    //   if (
    //     this.state.selected_cards[0].name === this.state.selected_cards[1].name
    //   ) {
    //     alert("Same");
    //   } else {
    //     alert("Not Same");
    //   }
    //   this.state.selected_cards.pop();
    //   this.state.selected_cards.pop();
    // }
  };

  shuffle = arr => {
    for (var i = arr.length - 1; i > 0; i--) {
      var j = Math.floor(Math.random() * (i + 1));
      var temp = arr[i];
      arr[i] = arr[j];
      arr[j] = temp;
    }
  };

  initGame = cards => {
    let rndGrid = [];

    for (var i = 0; i < 12; i++) {
      var randomInd = Math.floor(Math.random() * Math.floor(cards.length - 1));

      var card = cards[randomInd];

      this.state.rnd_card_list.push(card);

      cards.splice(randomInd, 1);
    }
    this.shuffle(this.state.rnd_card_list);

    for (var i = 0; i < 12; i++) {
      rndGrid.push(
        <Card
          key={i}
          handlePress={this.handlePress}
          card={this.state.rnd_card_list[i]}
        />
      );
    }
    return rndGrid;
  };

  render() {
    return (
      <StyledCardContainer>
        {this.initGame(this.state.cards)}
      </StyledCardContainer>
    );
  }
}

-------------------------------------------------------

//card component

export default class Card extends React.Component {
  render() {
    let icon_name = "question";
    let icon_color = "black";
    if (this.props.card.show) {
      icon_name = this.props.card.name;
      icon_color = this.props.card.color;
    }

    return (
      <TouchableOpacity onPress={() => this.props.handlePress(this.props.card)}>
        <StyledCard>
          <FontAwesome name={icon_name} size={40} color={icon_color} />
        </StyledCard>
      </TouchableOpacity>
    );
  }
}

1 Answer 1

1

You have a little bug in your code, specifically here:

this.setState({ rnd_list });

you have to tell to React which piece of the state you want to update, in this case you want to update the array of cards, otherwise React will rewrite everything with the array of cards

this.setState({ cards: rnd_list });
Sign up to request clarification or add additional context in comments.

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.