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
eventsis marked as required inEventList, but its value isundefined. 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();