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

时间:2017-02-09 10:13:12

标签: reactjs redux react-redux

代码是

main.js

import React, { Component, PropTypes } from 'react'
import render from 'react-dom'
import ReactDOM from 'react-dom'
import { createStore, applyMiddleware, compose, bindActionCreators} from 'redux'
import { Provider, connect } from 'react-redux'
import ReduxPromise from 'redux-promise'
import thunkMiddleware from 'redux-thunk'

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
import rootReducer from './src/reducers'
import App from './src/containers/App'

const store = createStore(
  rootReducer,
  compose(
    applyMiddleware(thunkMiddleware),
    window.devToolsExtension ? window.devToolsExtension() : f => f
  )
);


ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
)

app.js

import React, {PropTypes} from 'react'
import {bindActionCreators} from 'redux'
import {connect} from 'react-redux'
import Header from '../components/Header'
import MainSection from '../components/MainSection'
import * as TodoActions from '../actions'

const App = ({todos, actions}) => (
    <div>
        <Header addTodo={actions.addTodo}></Header>
        <MainSection todos={todos} actions={actions} />
    </div>
)
App.propTypes = {
    todos: PropTypes.array.isRequired,
    actions: PropTypes.object.isRequired
}

const mapStateTypes = state => ({
    todos: state.todos
})

const mapDispathToProps = dispatch => ({
    actions: bindActionCreators(TodoActions, dispatch)
})

export default connect(mapStateTypes, mapDispathToProps)(App)

MainSection.js

import React, {Component, PropTypes} from 'react'
import TodoItem from './TodoItem'

export default class MainSection extends Component {
    static propTypes = {
    }
    componentDidMount(){
    }
    render(){
        const todos = this.props.todos;
        const actions = this.props.actions

        return (
            <section className="main">
                <ul className="todo-list">
                    {todos.map((todo) => {
                        return (<TodoItem todo={todo} key={todo.id} {...actions} actions = {actions}/>)
                    })}
                </ul>
            </section>
        )
    }
}

TodoItem.js

import React, {Component, PropTypes} from 'react'

export default class TodoItem extends Component{
    static propTypes = {
        todo: PropTypes.object.isRequired,
        deleteTodo: PropTypes.func.isRequired,
    }

    handleDelete = () => {
        const todo = this.props;
        let deleteTodo = this.props.actions.deleteTodo;
        this.props.deleteTodo(todo.id)
    }
    handleChange =  () => {

    }
    render(){
        console.log(this.props)
        const {todo, deleteTodo} = this.props;
        let elem;
        elem = (
            <div className="views">
                <input type="checkbox" className="toggle" defaultChecked={todo.completed} onChange={this.handleChange}/>
                <label>{todo.text}</label>
                <button className="destory" onClick ={this.handleDelete}></button>
            </div>
        )

        return(
            <li className="editing">{elem}</li>
        )
    }
}

当我点击删除按钮时,出现错误

我知道问题出在这一行this.props.deleteTodo(todo.id)

但我不知道为什么以及如何修复

我在同一个问题上尝试了答案,但它没有工作

2 个答案:

答案 0 :(得分:0)

看起来redux-thunk在这种情况下不起作用,这是因为你的applyMiddleware有问题。

如果您发现需要将thunk传递给applyMiddleWare,请从文档中获取。

// Note: this API requires redux@>=3.1.0
const store = createStore(
  rootReducer,
  applyMiddleware(thunk)
);

但是你正在通过thunkMiddleware

const store = createStore(
  rootReducer,
  compose(
    applyMiddleware(thunkMiddleware), //should be thunk
    window.devToolsExtension ? window.devToolsExtension() : f => f
  )
);

查看文档here

答案 1 :(得分:0)

首先,你的架构错了。我注意到你使用了thunk + redux。但是你不能使用connect()用react redux包装你的组件。要使用连接,您需要使用import {connect} from 'react-redux'

导入它

在您想要删除项目的组件中,您应该使用操作DELETE_ITEM或您需要删除的元素的任何其他ID来分派操作创建者。

动作创建者应该发出动作&#34; DELETE_ITEM&#34;。它可以是异步的,因为您使用thunk中间件可以使用函数。 然后它应该删除项目并发出动作DELETED_ITEM(动作名称可以不同)

deleteReducer应该处理此操作,并且当执行DELETED_ITEM操作时,它应该更新商店。

在您的组件中,您需要添加

const mapStateToProps = (state) => {
    return {
        deletedItem: state.deleteReducer.item
    }
}

const mapDispatchToProps = (dispatch) => {
    return {
           onDeleteClick: () => {
                dispatch(actions.deleteItem()) // deleteItem is action creator
        }
    }

}

export default connect(
    mapStateToProps,
    mapDispatchToProps
)(TodoItem);

在您所在州之后,您将删除项目,并且您可以使用它执行某些操作,并且您可以使用

分发您的Todo组件中的点击操作
this.props.onDeleteClick();

如果我是你,我将以learning how redux flow works

开头