0

I am iteratively generating card components via db input (data). I am trying to figure out how to properly mapStatetoProps and mapDispatchtoProps for each card. Currently my addCard action is causing a TypeError as it says the addCard action is undefined.

My Reducer component has an initialState that contains a card array where I am trying to put all these cards.

There might be a solution that I am just missing, but I'd appreciate any suggestions.

class CardContainer extends React.Component {
  renderCard(item) {
    this.props.addCard(item); // <- this is where addCard gets called
    return (
      <CardTemplate
        title={item.name}
        address={item.address}
        phone={item.phone}
        hours={item.hours}
        key={item.service_id}
      />
    );
  }

  renderCards(cardData) {
    return cardData.map(this.renderCard);
  }

  render() {
    return <div className="Card_Container">{this.renderCards(data)}</div>;
  }
}

const mapStateToProps = state => {
  return {
    service_id: {
      name: state.rtS.rightMenu.cards,
      title: state.rtS.rightMenu.cards,
      address: state.rtS.rightMenu.cards,
      hours: state.rtS.rightMenu.cards
    }
  };
};

const mapDispatchToProps = dispatch => {
  return {
    addCard: item =>
      dispatch({
        type: actionTypes.ADD_CARD,
        payloadA: item.name,
        payloadAd: item.address,
        payloadP: item.phone,
        payloadH: item.hours,
        payloadS: item.service_id
      })
  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(CardContainer);

I probably have the addCard method written incorrectly or I don't have the mapStatetoProps return{} correct.

Tholle
  • 108,070
  • 19
  • 198
  • 189
  • Adding something to the Redux store directly in render is not something you want to do. Maybe you want to add a new item as a response to some event? – Tholle Mar 14 '19 at 14:01
  • 1
    To add a little context to Tholle's comment - you need to bear in mind that `render` is called repeatedly throughout the lifecycle of your component (when the props change, when the state changes, etc). This means that every time the component renders, you're going to fire a load of `addCard` actions. – Joe Clay Mar 14 '19 at 14:22
  • 1
    Thanks Tholle and Joe, this helped – Ryan Burgett Mar 14 '19 at 14:30

1 Answers1

0

This is an issue with context binding.

In fact when you do this

return cardData.map(this.renderCard);

this.renderCard isn't called with the component context, thus this.props will be undefined within renderCard

What you need to do is one of the following:

  1. Pass this to your map function: cardData.map(this.renderCard, this)
  2. Bind the context in the constructor: this.renderCard = this.renderCard.bind(this)
  3. Or use arrow functions when defining renderCard, so something like this:

renderCard = () => {...}

Hamza El Aoutar
  • 5,292
  • 2
  • 17
  • 23