redux Actions must be plain objects but I defined plain object

15,144

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).

Share:
15,144
g1eny0ung
Author by

g1eny0ung

Updated on July 27, 2022

Comments

  • g1eny0ung
    g1eny0ung almost 2 years

    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

  • Marko Gresak
    Marko Gresak over 7 years
    Great catch. I was looking at this when in search of an answer, but somehow missed it. To the author (who mentioned they are referring to official Reddit API example), this can be seen used here: redux.js.org/docs/advanced/…
  • g1eny0ung
    g1eny0ung over 7 years
    Yes, it's the answer! Thank you! But I change my code I found a new error: (0 , _outside2.default) is not a function.And thanks for @MarkoGrešak, I think you are right, I change my code to use mapDispatchToProps and connect it. I'm trying to solve new error.
  • Marko Gresak
    Marko Gresak over 7 years
    @g1eny0ung this looks like wrong use of import and/or export. It's hard to tell where, because you don't seem to have included all the code. If you don't figure it out yourself, post a new question.
  • g1eny0ung
    g1eny0ung over 7 years
    @MarkoGrešak Yes, you're right. The reducer code's import is wrong, I should use {} to bracket SIDEBARISVISIBLE. Thank you very much and thanks also @ nobody.English is not my native, so I only know "Thank you", This kind of gratitude(This sentence use translator, haha😝)
  • SagarPPanchal
    SagarPPanchal over 4 years
    perfect answer with explanation for beginners like me :) +1