React Redux TypeError:无法读取未定义的属性“ map”

时间:2018-10-15 10:17:01

标签: reactjs redux

我是React / Redux编码的初学者。我已经迷失在容器和组件的反应。在Redux之前,我可以轻松获取JSON数据。由于状态的复杂性,我决定学习Redux。时间不足使我不得不问这个问题。 我不明白为什么我的道具没有装满减速器。

(我正在尝试获取一个名为“事件”的json数组。)

这是我的代码:

./ actions / eventAction.js

    import C from './actionType';
export function fetchEvents() {

  return function (dispatch) {
    dispatch(requestEvent());
    return fetch('http://localhost:3000/json/data.json')
    .then(handleErrors)
    .then(
       response => response.json(),
       error => console.log('An error occurred.', error),
   )
    .then((json) => {
       dispatch(receivedEvents(json));
    },
   );

  };
 }

export const requestEvent = () => ({
  type: C.REQUEST_EVENT
});
export const receivedEvents = json => ({
  type: C.RECEIVED_EVENTS,
  payload: json.events
});


// Handle HTTP errors since fetch won't.
function handleErrors(response) {
  if (!response.ok) {
    throw Error(response.statusText);
  }
  return response;
}

./ Component / Event.js

import React from 'react'
import PropTypes from 'prop-types'

export const Event = ({ title, description, category, tags, img, onClick}) => (
    <div className="card eq-event-card mb-5">
    <img className="img-speech-bubble card-img-top eq-event-img" src={img} alt="Card image cap"></img>
    <div className="card-body shadow-lg">
      <div className="container d-flex flex flex-column mb-5">
        <div className="fab-button justify-content-center">

        <i className="fas fa-plus my-3" />
        </div>
        <div className="eq-event-header container d-flex flex-row justify-content-between">
          <div className="eq-event-title col-md-9">
          <p className="card-title h3 text-right">
             {title}
          </p>
          </div>
          <div className="eq-event-cat text-center col-md-3" >
                 <p className="h5">{category})</p>
          </div>
        </div>
        <div className="container">
          <div className="row">
            <div className="eq-event-desc col-md-8 col-sm-12">
              <p className="text-justify card-text text-muted">
                {description}
              </p>
            </div>
            <div className="eq-event-tag col-md-4 col-sm-12 ">
              <ul className="text-justify">
                <li className="text-muted">{tags}</li>
              </ul>
            </div>
          </div>
        </div>
      </div>
      <div className="d-flex justify-content-center">
        <button onClick={onClick} href="#" className="more-button btn btn-primary">اطلاعات بیشتر <i className="fas fa-arrow-left" /></button>
      </div>
    </div>
  </div>

)


Event.propTypes = {
    id: PropTypes.number.isRequired,
    title: PropTypes.string.isRequired,
    desc: PropTypes.string.isRequired,
    category: PropTypes.string.isRequired,
    tags: PropTypes.arrayOf(PropTypes.string),
    onClick: PropTypes.func.isRequired,
    img: PropTypes.string.isRequired
  }

export default Event

./ Components / EventList.js

import React from 'react'
import PropTypes from 'prop-types'
import Event from './Event'

export const EventList = ({events}) => (

    events.map((event, index) => (
        <Event key={index} {...event} />

    ))

)

EventList.propTypes = {
    events: PropTypes.arrayOf(
        PropTypes.shape({
            id: PropTypes.number.isRequired,
            title: PropTypes.string.isRequired,
            desc: PropTypes.string.isRequired,
            category: PropTypes.string.isRequired,
            tags: PropTypes.arrayOf(PropTypes.string),
            img: PropTypes.string.isRequired
        }).isRequired
    ).isRequired,
}

export default EventList

./ containers / EventListHandler

import { connect } from 'react-redux'
import {fetchEvents, receivedEvents} from '../actions/eventAction'
import EventList from '../components/EventList'
import {C} from '../actions/actionType'
const getEvents = (events, actionType) => {
    switch(actionType) {
        case C.RECEIVED_EVENTS:
            return events
        default: 
            throw new Error('Errorororor!')
    }
}

const mapStateToProps = state => {
    return {
        events: getEvents(state.events, C.RECEIVED_EVENTS )
    }
}

const mapDispatchToProps = dispatch => {
    return ({
      fetchEvents: () => {dispatch(receivedEvents)}
    })
}

const ShowEventList = connect(
    mapStateToProps,
    mapDispatchToProps
)(EventList)

export default ShowEventList

./ reducers / eventReducer.js

import {C} from '../actions/actionType';

export default (state = [], action) => {
    switch (action.type){

      case C.RECEIVED_EVENTS:
      return [
        ...state,
        Object.assign({}, action.payload)
      ];

      default:
        return state;
    }
  };

./ reducers / index.js

    import { combineReducers } from 'redux';
import EventReducer from './eventReducer';

export const rootReducer = combineReducers({
 events: EventReducer
});

export default rootReducer;

和错误消息:

  

警告:道具类型失败:道具events被标记为   EventList,但其值为undefined。       在EventList中


更新: src / index.js

    import React from 'react';
import ReactDOM from 'react-dom';
import {Place, Time} from './plan';
import {Event} from './containers/EventListHnadler'
import * as serviceWorker from './serviceWorker';
import { Provider } from 'react-redux';
import configureStore from './store/configureStore';
import rootReducer from './reducers/index'
const store = configureStore(rootReducer);

ReactDOM.render(
    <Provider store={store}>
        <Event />
    </Provider>, document.getElementById('event-entry'));
    ReactDOM.render(<Place />, document.getElementById('select-place'))
    ReactDOM.render(<Time />, document.getElementById('select-time'))


serviceWorker.register();

1 个答案:

答案 0 :(得分:1)

我真的不确定您在哪里使用此ShowEventList 但是只要有条件就可以使用

 render(){
  <div>
   {
    events && events.length>0 &&
    <ShowEventList events={this.events} />
   }

  </div>
  }

这将确保您的EventList组件始终收到道具