Redux的Actions必须是普通对象,但我定义了一个普通对象

8
I use Redux和React构建我的网站,想使用Redux控制侧边栏的显示。该侧边栏由Semantic-UI-React定义。因为我想跨另一个组件来控制它,所以我在侧边栏的父组件中定义了props: const { visible, dispatch } = this.props,并有一个onClick函数来处理它。以下是我的代码。

未捕获的错误:操作必须是纯对象。使用自定义中间件进行异步操作。

这个错误困扰了我一个下午,我不知道为什么!以下是我的操作代码:
**action**

export const SIDEBARISVISIBLE = 'sidebarVisible'

export function sidebarVisibleAction() {
  return { type: SIDEBARISVISIBLE }
}

如您所见,我定义了一个返回纯对象的动作创建器。

以下是我的 reducer 代码:

**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

此外,我的商店代码是:
**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)
  )
}

然后,我的组件代码(部分):
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)

最后,我的路由器:
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>
        )
    }
}

所以,我搜索了这个错误的答案,大多数人都说,你必须设置redux-thunk并使用ApplyMiddleware来使用它,这是最简单的方法。但我定义的操作是纯对象。如果我不使用redux-thunk,我认为我也不会遇到这个错误。所以,我很困惑,如何解决这个问题?
感谢所有的帮助。

不确定这是否相关,因此我将其编写为注释。你为什么要使用dispatch?你应该在connect中使用mapDispatchToProps并将动作作为this.props.actionName获取。只需确保使用道具版本而不是导入的版本即可。我也犯过这个错误太多次了:D - Marko Gresak
关于你的代码,还有一个普遍的评论,如果你已经在使用redux,为什么还要使用组件状态?如果你正在使用redux,最好通过redux进行所有状态管理,代码更容易理解和测试。额外的好处是这样做,你不需要类,可以使用纯组件。 - Marko Gresak
@MarkoGrešak 是的,我会为你解释你所说的内容。首先,我使用 dispatch,因为我参考了官方的redux Reddit API 代码。其次,我使用的状态仅用于激活项目,这是semantic-ui-react的默认实现,因此我没有更改它。 - g1eny0ung
除了一些非常基本的例子,我在我的代码中没有使用dispatch,因此我没有看到错误,但是@nobody找到了答案。但是我建议的仍然可以工作,因为mapDispatchToProps将操作包装为调度调用,因此您可以将操作用作常规函数,并省略dispatch(action(args))语法,而选择我认为更清晰的action(args)调用。 - Marko Gresak
1个回答

27

这里:

dispatch(sidebarVisibleAction)

你正在将函数sidebarVisibleAction传递给了dispatch。你应该调用它并传递结果,这样代码将会像这样:

dispatch(sidebarVisibleAction())

(现在dispatch将获得一个对象,而不是一个函数)。


太棒了。我在寻找答案时看到了这个,但不知何故错过了它。对于提到他们正在参考官方Reddit API示例的作者,可以在此处查看其使用:http://redux.js.org/docs/advanced/ExampleRedditAPI.html#containersasyncappjs - Marko Gresak
1
是的,这就是答案!谢谢!但我改变了我的代码,我发现了一个新的错误:(0,_outside2.default)不是一个函数。感谢@MarkoGrešak,我认为你是对的,我改变了我的代码来使用mapDispatchToProps并连接它。我正在尝试解决新的错误。 - g1eny0ung
@g1eny0ung,这看起来像是import和/或export的错误使用。很难确定在哪里出错了,因为您似乎没有包含所有的代码。如果您自己无法解决,请发布一个新问题。 - Marko Gresak
@MarkoGrešak 是的,你说得对。reducer代码里的import写错了,我应该用{}来括起来SIDEBARISVISIBLE。非常感谢你,还要感谢@ nobody。英语不是我的母语,所以我只懂“谢谢”。这样的感激之情(这句话使用翻译器,哈哈)。 - g1eny0ung
完美的答案并附有解释,非常适合像我这样的初学者 :) +1 - SagarPPanchal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接