I use redux + react to build my website, and I want to use redux to control a sidebar visible.The sidebar is defined by semantic-ui-react.Because I want to control it across another component, so I defined the props in sidebar's parent component const { visible, dispatch } = this.props
, there is a onClick function to handle this. I will show my code.
Uncaught Error: Actions must be plain objects. Use custom middleware for async actions.
This error confused me one afternoon, and I don't know why! This is my action code:
**action**
export const SIDEBARISVISIBLE = 'sidebarVisible'
export function sidebarVisibleAction() {
return { type: SIDEBARISVISIBLE }
}
As you can see, I defined an action creator returned a plain object.
And this is my reducer code:
**reducer**
import SIDEBARISVISIBLE from '../actions/outside.js'
function sidebarVisible(state = {
sidebarIsVisible: false
}, action) {
switch (action.type) {
case SIDEBARISVISIBLE:
return Object.assign({}, state, {
sidebarIsVisible: !state.sidebarIsVisible
})
default:
return state
}
}
export default sidebarVisible
Also my store code:
**store**
import { createStore, applyMiddleware, compose } from 'redux'
import thunk from 'redux-thunk'
import sidebarVisible from '../reducers/outside.js'
export default initialState => {
return createStore(
sidebarVisible,
initialState,
applyMiddleware(thunk)
)
}
Then, my component code(part of):
class OutsideView extends Component {
constructor(props) {
super(props)
this.state = { activeItem: '' }
}
handleItemClick = (e, { name }) => this.setState({ activeItem: name })
render() {
const { activeItem } = this.state
const { visible, dispatch } = this.props
return (
<div>
<SidebarNav visible={ visible } />
......
<Menu.Item
name='sidebar'
active={ activeItem === 'sidebar'}
onClick={ (e, {name}) => {
this.setState({ activeItem: name })
dispatch(sidebarVisibleAction)
} }>
<Icon color='red' name='list' />
</Menu.Item>
OutsideView.PropTypes = {
visible: PropTypes.bool.isRequired,
dispatch: PropTypes.func.isRequired
}
function mapStateToProps(state) {
return {
visible: state.sidebarIsVisible,
}
}
export default connect(
mapStateToProps
)(OutsideView)
The last, my Router:
import configureStore from './store/index.js'
const store = configureStore()
export default class Root extends Component {
render() {
return (
<Provider store={ store }>
<Router history={ browserHistory }>
<Route path="/" component={ OutsideRedux }>
<Route path='register' component={ Register } />
<Route path='login' component={ Login } />
<Route path='blog' component={ Blog } />
<Route path='about' component={ About } />
<Route path='home' component={ Home } />
<Route path='ask' component={ Ask } />
<Route path='panel' component={ Panel } />
<Route path='setting' component={ Setting } />
<Route path='user' component={ User } />
</Route>
</Router>
</Provider>
)
}
}
So, I search for answer for this error, most of them say, you have to setup redux-thunk and with ApplyMiddleware to use it, the simplest way.But the action I defined is plain object.If I don't use redux-thunk, I think I will not encounter this error either.So, I'm very confused, how to solve this?
Thanks for all the help
dispatch
? You should usemapDispatchToProps
inconnect
and get the action asthis.props.actionName
. Just make sure you use the props version and not the imported one. Made this mistake too many times :D – Marko Gresakdispatch
in my code, therefore I failed to see the error, but @nobody found the answer. But what I suggested would still work, becausemapDispatchToProps
warps the action as dispatch call, so you can use the action as regular function and omit thedispatch(action(args))
syntax in favor of, in my opinion, more cleanaction(args)
call. – Marko Gresak