Reputation: 2204
I have such a problem in reducers
to todos trying to assigntodos: action.payload.data
. I have error:
Cannot read property 'data' of undefined error.
const rootReducer = (state = initialState, action) => {
switch (action.type) {
case 'GET_TODOS':
return {
...state,
todos: action.payload.data
};
default:
return state;
}
};
Demo here: https://stackblitz.com/edit/react-ewpquh
actions
import axios from 'axios';
export const GET_TODOS = 'GET_TODOS';
export const FETCH_SUCCESS = 'FETCH_SUCCESS';
export const FETCH_FAILURE = 'FETCH_FAILURE';
export const getTodos = () =>
dispatch => {
dispatch({type: GET_TODOS});
return axios({
url: 'https://jsonplaceholder.typicode.com/todos',
method: 'GET',
})
.then(data => {
console.log(data);
dispatch({type: FETCH_SUCCESS, payload:{
data
}});
})
.catch(error => {
console.log(error);
dispatch({type: FETCH_FAILURE})
});
};
Todos
import React, { Component } from 'react';
import { connect } from 'react-redux';
import {getTodos} from '../.././actions';
class Todos extends Component {
componentDidMount() {
this.props.getTodos();
}
render() {
return (
<ul>
{this.props.todos.map(todo => {
return <li key={todo.id}>
{todo.title}
</li>
})}
</ul>
);
}
}
const mapStateToProps = state => {
console.log(state.todos);
const { todos } = state;
return {
todos
};
};
const mapDispatchToProps = dispatch => ({
getTodos: () => dispatch(getTodos())
});
export default connect(mapStateToProps, mapDispatchToProps)(Todos);
reducers
import {GET_TODOS} from '../../actions';
const initialState = {
todos: []
};
const rootReducer = (state = initialState, action) => {
switch (action.type) {
case 'GET_TODOS':
return {
...state,
todos: action.payload.data
};
default:
return state;
}
};
export default rootReducer;
store
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from '../reducers';
const store = createStore(rootReducer, applyMiddleware(thunk));
export default store;
Upvotes: 0
Views: 1922
Reputation: 17858
Your actions/index.js file should be:
import axios from 'axios';
export const GET_TODOS = 'GET_TODOS';
export const FETCH_SUCCESS = 'FETCH_SUCCESS';
export const FETCH_FAILURE = 'FETCH_FAILURE';
export const getTodos = () =>
dispatch => {
dispatch({type: GET_TODOS});
axios({
url: 'https://jsonplaceholder.typicode.com/todos',
method: 'GET',
})
.then(response => {
console.log(response.data);
const data = response.data;
dispatch({type: FETCH_SUCCESS, payload:{
data
}});
})
.catch(error => {
console.log(error);
dispatch({type: FETCH_FAILURE})
});
};
And reducers/index.js file should be:
import {GET_TODOS} from '../../actions';
const initialState = {
todos: [],
loading: false,
error: null
};
const rootReducer = (state = initialState, action) => {
switch (action.type) {
case 'GET_TODOS':
return {
...state,
loading: true
};
case 'FETCH_SUCCESS':
return {
...state,
todos: action.payload.data,
loading: false
};
case 'FETCH_FAILURE':
return {
...state,
loading: false,
error: action.error
};
default:
return state;
}
};
export default rootReducer;
Upvotes: 1
Reputation: 78
first, you should add case FETCH_SUCCESS to reducer :
case 'FETCH_SUCCESS':
return {
todos: action.payload.data
};
after that, you need to replace this code on action file:
.then(result => {
const data = result.data
dispatch({type: FETCH_SUCCESS, payload:{
data
}});
})
finally, check that TodosList is not empty on component:
return (
<ul>
{this.props.todos && this.props.todos.map(todo => {
return <li key={todo.id}>
{todo.title}
</li>
})}
</ul>
);
Upvotes: 0
Reputation: 1
The function 'GET_TODOS'
is triggered before the promise is fulfilled and executed without sending the payload
, The function 'GET_TODOS'
must be executed when the promise is fulfilled to be able to send the payload
'data'
, the function getTodos would remain following way:
export const getTodos = () =>
dispatch => {
return axios({
url: 'https://jsonplaceholder.typicode.com/todos',
method: 'GET',
})
.then(data => {
dispatch({type: GET_TODOS, payload : data});
})
.catch(error => {
console.log(error);
dispatch({type: FETCH_FAILURE})
});
};
Upvotes: 0
Reputation: 416
check your actions.js line
dispatch({type: GET_TODOS});
You are not passing any payload with this dispatch, May its FETCH_SUCCESS that needs to be in reducer instead of GET_TODOS
Upvotes: 1
Reputation: 799
The error that is coming is for the GET_TODOS Action Type, Look at your action (index file), you are not passing payload object while dispatching GET_TODOS.
Also, you are passing an action called FETCH_SUCCESS, but you do not have any case for it in your reducer. Did you intend to dispatch GET_TODO's here?
Upvotes: 1