I am having a react-redux action creation problem. My props are an empty object when I log props at the life cycle method componentDidMount()
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchSurveys } from '../../actions/index';
export class SurveyList extends Component {
componentDidMount() {
console.log(this.props);
this.props.fetchSurveys();
}
renderSurveys() {
return (
this.props.surveys.length &&
this.props.surveys.map(survey => {
return (
<div className="card blue-grey darken-1" key={survey._id}>
<div className="card-content">
<span className="card-title">{survey.title}</span>
<p>{survey.body}</p>
<p className="right">
Sent On: {new Date(survey.dateSent).toLocaleDateString()}
</p>
</div>
<div className="card-action">
<a>Yes: {survey.yes}</a>
<a>No: {survey.no}</a>
</div>
</div>
);
})
);
}
render() {
return <div>{this.renderSurveys()}</div>;
}
}
function mapStateToProps({ surveys }) {
return { surveys };
}
export default connect(mapStateToProps, { fetchSurveys })(SurveyList);
Now according to the react-redux docs by default dispatch is included on the props so we do not need to explicitly call a mapDispatchToProps in the connect method in order to hit our action creators. fetchSurveys() is an action creator and I expect it to return a list of surveys which I then render.
However this.props = {}; so of course I cannot call .map on undefined at renderSurveys() as I do not get the surveys property on props either.
I am really troubled by why my props are empty. Can anybody shed some light onto this problem, I would be very grateful. I have tried using bindActionCreators and having my own mapDispatchToProps method, this doesn't work either.
Here are my actions.
import axios from 'axios';
import { FETCH_USER, FETCH_SURVEYS } from './types';
export const fetchUser = () => async dispatch => {
const res = await axios.get('/api/current_user');
dispatch({ type: FETCH_USER, payload: res.data });
};
export const handleToken = token => async dispatch => {
const res = await axios.post('/api/stripe', token);
dispatch({ type: FETCH_USER, payload: res.data });
};
export const submitSurvey = (values, history) => async dispatch => {
const res = await axios.post('/api/surveys', values);
history.push('/surveys');
dispatch({ type: FETCH_USER, payload: res.data });
};
export const fetchSurveys = () => async dispatch => {
console.log('called');
const res = await axios.get('/api/surveys');
dispatch({ type: FETCH_SURVEYS, payload: res.data });
};
My surveys reducer -
import { FETCH_SURVEYS } from '../actions/types';
export default function(state = [], action) {
switch (action.type) {
case FETCH_SURVEYS:
return action.payload;
default:
return state;
}
}
Combined reducer -
import { combineReducers } from 'redux';
import authReducer from './authReducer';
import { reducer as reduxForm } from 'redux-form';
import surveysReducer from './surveysReducer';
export default combineReducers({
auth: authReducer,
form: reduxForm,
surveys: surveysReducer
});
this.props.dispatch(fetchSurveys()
is what to docs mean. Thedispatch
isn't automatically wired up unless you usebindActionCreators
. You probably need to defaultsurveys
to[]
as well. - Davin Tryon