Error rendering a component after Link - React

I am facing an error when I am in a component, then I click on the Link inside and try to get back.

Basically the flow is: WeddingList Page -> Click -> Wedding Page -> Click -> WeddingList

So, when I click to go back, this error is triggered:

TypeError: this.props.weddings.map is not a function WeddingList.renderWeddings

Here is my code:

WeddingList.js

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchWeddings } from '../../actions';
import { Link } from 'react-router-dom';

class WeddingList extends Component {
  componentWillMount() {
    this.props.fetchWeddings();
  }

  renderWeddings() {
    return this.props.weddings.map(wedding => {
      return (
        <div className="row" key = { wedding._id }>
        <div className="col s10 offset-s1" key={wedding._id}>
          <div className="card blue-grey darken-1" key={wedding._id}>
            <div className="card-content white-text">
              <span className="card-title">{wedding.coupleName1} & {wedding.coupleName2}</span>
            </div>
            <div className="card-action">
              <Link 
                to={'/wedding/'+wedding.pageName} 
                className="btn">
                Visit!
              </Link>
            </div>
          </div>
        </div>
        </div>
      );
    })
  }

  render() {
    return (
      <div>
        {this.renderWeddings()}
      </div>
    );
  }
}

function mapStateToProps({ weddings }) {
  return { weddings };
}

export default connect(mapStateToProps, { fetchWeddings })(WeddingList);

Wedding.js

import React from 'react';
import WeddingPage from './weddings/WeddingPage';
import { Link } from 'react-router-dom';

const Wedding = props => {
  return (
    <div>
      <WeddingPage {...props}/>
      <Link to={'/weddings'} className="btn">Back</Link>
    </div>
  );
}

export default Wedding;

weddingsReducer.js

import { FETCH_WEDDINGS, FETCH_WEDDING } from '../actions/types';

export default function(state = [], action) {
  switch (action.type) {
    case FETCH_WEDDINGS:
      return action.payload;
    case FETCH_WEDDING:
      return action.payload;
    default:
      return state;
  }
}

reducers.js

import { combineReducers } from 'redux';
import { reducer as reduxForm } from 'redux-form'
import authReducer from './authReducer';
import weddingsReducer from './weddingsReducer';

export default combineReducers({
  auth: authReducer,
  form: reduxForm,
  weddings: weddingsReducer,
  wedding: weddingsReducer
});

Thanks in advance

Upvotes: 0

Views: 93

Answers (1)

Alex Borodin
Alex Borodin

Reputation: 2034

It looks like the this.props.weddings is undefined in the first render. It may happen if weddings are received by ajax request( fetchWeddings does it ). The solution is to set initial state in your reducers.js:

import { FETCH_WEDDINGS, FETCH_WEDDING } from '../actions/types';

const initialState = { weddings: [] }

export default function(state = initialState, action) {
  switch (action.type) {
    case FETCH_WEDDINGS:
      return {...state, weddings: action.payload.weddings};
    case FETCH_WEDDING:
      return {...state, wedding: action.payload.wedding};
    default:
      return state;
  }
}

Also, you can validate your PropTypes in WeddingList.js:

import PropTypes from 'prop-types';

class WeddingList extends Component {
  static propTypes = {
    wedding:  PropTypes.array.isRequired
  }
  ....
}

Upvotes: 1

Related Questions