hi,I'm new to this
the error message is
browser.js:40 Uncaught Invariant Violation:mapStateToPropsmust return an object. Instead received [object Object].
1.
case 'TOGGLE_TODO':
return state.todos.map(function(state){
if(state.id!==action.id){
return state
};
return {...state,completed:true}
});
(from egghead )
this will throw the error,but I don't know why.
But if I not using return before state.todos.map it is fine
2.
case 'TOGGLE_TODO':
state.todos.map(function(state){
if(state.id!==action.id){
return state
};
//return state.completed=true}
return {...state,completed:true}
});
if I change to this it will not change the store
3.
only
case 'TOGGLE_TODO':
state.todos.map(function(state){
if(state.id!==action.id){
return state
};
//return state.completed=true}
return state.completed=true
});
and
case 'TOGGLE_TODO':
state.todos.map(function(state){
if(state.id!==action.id){
return state
};
//return state.completed=true}
return Object.assign(state,{completed:true})
});
can successfully update the store and no error message,but this will also change the prev state,
how can I change this code? Thanks for reply.
If you found the solution please share it in a comment so other people who find this issue know how you solved it. Thanks!
I was using below works good ,but still don't know why others give error when it return [object Object]but still says must return an object
case 'TOGGLE_TODO':
return Object.assign({},state,{todos:state.todos.map(function(state){
if(state.id!==action.id){
return state
};
return {...state,completed:!state.completed}
}) }
)
Why are you posting the reducer code? The error says mapStateToProps returned something that isn’t a plain object. Not the reducer.
My guess is your mapStateToProps returns something like state.todos which will not work. The point of that function is to provide props to component, so it has to return an object with those props. Rather than pass state.todos you would probably want { todos: state.todos }.
If this is the case, we need to make a better error message that detects arrays. Contributions are welcome.
The problem here is that the error message isn't clear enough, an object is being passed in but it isn't a plain object until EasonWang01 uses Object.assign(). checkStateShape calls _.isPlainObject which requires Object.prototype == null or to have been created with Object.constructor. The error message could probably be updated to read %sToProps must return a plain object. Instead received %s
The wording for computeMergedProps could be updated as well to reflect this.
the mapStateToProp is look like this
import React, { Component } from 'react'
import TodoInput from './TodoInput.js'
import TodoList from './TodoList.js'
import {connect} from 'react-redux'
class App extends Component {
render() {
return (
<div>
<h1>Todo list</h1>
<TodoInput />
<TodoList todos={this.props}/>
</div>
)
}
}
function mapStateToProp(state){
return state
}
export default connect(mapStateToProp)(App)
I guess it might be that I'm not using combineReducer so I need to return the full state to store,not sure~
(◕ᴥ◕) ʕ·ᴥ·ʔ
Can you provide a full project reproducing the problem on GitHub? These pieces don't quite add up in my mind. For example it is strange you are passing the whole props object as todos prop down.
Hi, https://github.com/EasonWang01/Redux-tutorial/tree/link it's the origin version.
in Redux folder=> reducer.js
change to below and click initial for demo
let getId = 1 ;
export default function reducer(state,action){
switch(action.type){
case 'ADD_TODO':
return( Object.assign({},state,{
todos:[{
text:action.text,
completed:false,
id:getId++
},...state.todos]
})
)
case 'TOGGLE_TODO':
return state.todos.map(function(state){
if(state.id!==action.id){
return state
};
return {...state,completed:true}
});
case 'SET_VISBILITY_FILTER':
return Object.assign({},state,{visbility:action.filter})
default:
return state;
}
}
then the error appear,I think it just some miss typed by me, not a big problem need to solve
( ´ ▽ ` )b
But one thing I found is when some error occur in reducer.js the console.error will always point to some component file rather than reducer.js file.
Normally you return an object like { todos: Array<Todo> }:
case 'ADD_TODO':
return( Object.assign({},state,{
todos:[{
text:action.text,
completed:false,
id:getId++
},...state.todos]
})
)
However when handling TOGGLE_TODO, you return just an Array<Todo>:
case 'TOGGLE_TODO':
return state.todos.map(function(state){
if(state.id!==action.id){
return state
};
return {...state,completed:true}
});
This is missing Object.assign({}, state, { todos: ... }).
Then this state gets returned from mapState() which is where the error fires. Fixing the reducer to return the object would fix the problem. I also suggest you to use reducer composition as Egghead series shows, rather than put all the code into a single big reducer.
Hope it helps!
thanks!
Most helpful comment
Why are you posting the reducer code? The error says
mapStateToPropsreturned something that isn’t a plain object. Not the reducer.My guess is your
mapStateToPropsreturns something likestate.todoswhich will not work. The point of that function is to provide props to component, so it has to return an object with those props. Rather than passstate.todosyou would probably want{ todos: state.todos }.If this is the case, we need to make a better error message that detects arrays. Contributions are welcome.