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
For example, if you try to return another function, especially an async function, inside this action, redux doesn’t know how to handle this natively. To fix that, you will need custom middleware injected on your redux.
That means you may not put other things into the Redux state - no class instances, built-in JS types like Map / Set Promise / Date, functions, or anything else that is not plain JS data. The root Redux state value is almost always a plain JS object, with other data nested inside of it.
State, Actions, and Reducers are the building blocks of Redux. Every Redux app has state values, creates actions to describe what happened, and uses reducer functions to calculate new state values based on the previous state and an action. Here's the contents of our app so far: redux-fundamentals-example - CodeSandbox.
I can still return an normal object with a type property, that is an option, with Redux-Thunk we can still make normal action creators that return objects, but we don't have to return an action. With Redux-Thunk we can use async/await syntax, because this syntax is only going to modify the return value of the inner function.
Here:
dispatch(sidebarVisibleAction)
you are passing function sidebarVisibleAction
to dispach
. You should call it and pass result, so the code will look like:
dispatch(sidebarVisibleAction())
(now dispatch
will get object, not a function).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With