Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

redux Actions must be plain objects but I defined plain object

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

like image 267
g1eny0ung Avatar asked Jan 21 '17 14:01

g1eny0ung


People also ask

Why can’t I return a function in a redux action?

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.

Can you put other things in a redux state?

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.

What are the building blocks of Redux?

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.

What is the difference between Redux-thunk and normal action creators?

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.


1 Answers

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

like image 52
Marcin Sucharski Avatar answered Sep 24 '22 03:09

Marcin Sucharski