尝试从 fabric.js 事件处理程序分派操作会导致 "Reducers may not dispatch actions."

Trying to dispatch an action from the fabric.js event handler causes "Reducers may not dispatch actions."

我正在使用 fabric.js 和 redux/react 开发应用程序。

很快,我想要的是当我在 canvas 上添加一个对象时,它被选中并写入应用程序状态。

这是我现在所拥有的 - 当我在 canvas 事件上单击一个对象时 "object:selected" 被触发,我分派操作以将所选对象保存到我的应用程序状态中。

fabricCanvas.on('object:selected', function(options) {
    store.dispatch({ 
       type: 'SET_SELECTED_OBJECT',
       object: options.target 
    })
})

它工作得很好,但是当我尝试将对象添加到 canvas 时自动将其设置为选中时,乐趣就开始了。

fabricCanvas.on('object:added', function(options) {
   fabricCanvas.setActiveObject(options.target) 
})

函数 setActiveObject() 触发了 "object:selected",这是非常合乎逻辑的,我希望我的处理程序可以派发,但它却授予我

Uncaught Error: Reducers may not dispatch actions.

我知道从 reducer 派发动作有限制,但我不明白为什么 Redux 认为我会尝试这样做。

我从事件处理程序触发了另一个事件,该事件调度了一个动作。 我做错了什么?

更新:
两个处理程序都在 index.js 中定义,紧接在商店和结构定义之后。

import 'babel-polyfill';
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import rootReducer from './reducers'
import App from './components/App'

import { clearSelectedObject, setSelectedObject, addObject } from './actions'
import initialState from './initialState.js'



let store = createStore(rootReducer, initialState, window.devToolsExtension && window.devToolsExtension())


render(
    <div id="ocdc-holder">
        <Provider store={store}>
            <App />
        </Provider> 
    </div>,
    document.getElementById('root')
)

const fabricCanvas = new fabric.Canvas('canvas-lower')

fabricCanvas.on('object:added', function(options) {
   fabricCanvas.setActiveObject(options.target) 
})

fabricCanvas.on('object:selected', function(options) {
    store.dispatch({ 
       type: 'SET_SELECTED_OBJECT',
       object: options.target 
    })
})

这是我的 reducers.js 文件 http://pastebin.com/SFHZ9jVr

您的处理ADD_TEXT操作reducers.js文件:

const newTextObj = new fabric.Text(action.payload.text)
fabricCanvas.add(newTextObj)
fabricCanvas.fire('object:selected')
return {
    ...state,
    objects: [
        ...state.objects,
        newTextObj
    ]
}

你不应该在 reducer 中触发任何事件。

解雇他们 before/after 调度 ADD_TEXT 行动:

// Somewhere in component, or where you are dispatching `ADD_TEXT` action.
const newTextObj = new fabric.Text(action.payload.text)
fabricCanvas.add(newTextObj)
fabricCanvas.fire('object:selected')

Reducers 应该没有副作用。 reducer 应该做的一切,就是 return 新状态,使用以前的状态和分派的动作。

您收到此错误,因为您在 reducer 中触发了 'object:selected' 事件,它会产生动作调度。