0

I'm very beginner at React/Redux coding. I've been lost in containers and components of react. Before Redux, I could fetch JSON data easily. Because of state complexity, I decided to learn Redux. Lack of time made me to ask this question. I can't understand why my props aren't filled with reducer.

(I'm trying to fetch an json array which name is "events".)

Here is my code:

./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;

and error message:

Warning: Failed prop type: The prop events is marked as required in EventList, but its value is undefined. in EventList


UPDATE: 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 Answer 1

1

i am really not sure where you are using this ShowEventList but where ever it is use if condition

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

  </div>
  }

this will make sure that your EventList components always receives the props

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

6 Comments

I don't exactly where I'm supposed to put it.
i wasnt able to find it in your code. where is this component being called from ?
I wrapped <Event/> with <Provider> tag in index.js. I added it in my question.
if you put <Event /> in your root. then where would u use <EventList /> this whole organisation is complicated.
Yes, It is. I’m lost in this maze.
|

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.