首页 > 解决方案 > 错误:操作必须是普通对象。在删除按钮中使用自定义中间件进行异步操作?

问题描述

在用户从列表中删除文件后,我试图获得一个反应动作来获取文件列表。

在 App.js 中,我将一个handleClick函数传递给嵌套组件。

应用程序.js

    class App extends Component {
    static propTypes = {
        files: PropTypes.array.isRequired,
        isFetching: PropTypes.bool.isRequired,
        dispatch: PropTypes.func.isRequired,
        handleClick : PropTypes.func
    };

    componentDidMount() {
        const {dispatch} = this.props;
        dispatch(fetchFiles);
    }

    handleClick = fileId => {
        const {dispatch} = this.props;
        deleteFileById(dispatch,fileId);
    };

    render() {
        const {files, isFetching, dispatch} = this.props;
        const isEmpty = files.length === 0;
        return (
            <div>
                <h1>Uploadr</h1>
                {isEmpty
                    ? (isFetching ? <h2>Loading...</h2> : <h2>No files.</h2>)
                    : <div style={{opacity: isFetching ? 0.5 : 1}}>
                        <Files files={files} handleClick={this.handleClick}/>
                    </div>
                }
            </div>
        )
    }
}

const mapStateToProps = state => {
    const {isFetching, items: files} = state.files;

    return {
        files,
        isFetching,
    }
};


export default connect(mapStateToProps)(App)

文件.js

import React from 'react'
import PropTypes from 'prop-types'

const Files = ({files, handleClick }) => (
    <ul>
        {files.map((file, i) =>
            <li key={i}>{file.name}
                <button onClick={() => (handleClick(file.id))}>Delete</button>
            </li>
        )}
    </ul>
);

Files.propTypes = {
    files: PropTypes.array.isRequired,
    handleClick: PropTypes.func.isRequired
};

export default Files

动作.js

我想在删除操作完成后触发从 API 获取新文件列表的请求。

export const deleteFileById = (dispatch, fileId) => {
    dispatch(deleteFile);
    return fetch(`/api/files/${fileId}`, {method : 'delete'})
        .then(dispatch(fetchFiles(dispatch)))
};

export const fetchFiles = (dispatch) => {
    dispatch(requestFiles);
    return fetch('/api/files')
        .then(response => response.json())
        .then(json => dispatch(receiveFiles(json)))
};

但是我收到以下错误

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

实现这一点的最佳方法是什么

标签: javascriptreactjsredux

解决方案


一个动作将调度另一个动作,但不会调度事件处理函数。

您无需从组件中分派 deleteFileById,因为这是一个在动作中导出的函数,它将分派一个动作。

请删除 handleClick 中的调度以工作。

错误一:

handleClick = fileId => {
    this.props.deleteFileById(dispatch(this.props.dispatch,fileId));
};

正确一:

handleClick = fileId => {
    this.props.deleteFileById(this.props.dispatch,fileId);
};

关于 this.props.deleteFileById 不是函数。

有很多方法可以访问组件中的操作。下面介绍几种方法

您需要安装道具类型

npm install -s 道具类型

如果您的组件是测试然后设置道具类型如下

import PropTypes from 'prop-types';
import React, {Component} from 'react';

class Test extends Component{
    render(){
      return(
        <div</div>
      )
    }
}

Test.propTypes = {
  deleteFileById: PropTypes.func
}

如果您使用的是 redux 连接,那么

没有道具类型

import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as actions from '../actions';

class Test extends Component{
        render(){
          return(
            <div</div>
          )
        }
    }

export default connect(null, {...actions})(Test);

或者

使用内置的 react proptypes,您无需单独安装 prop-types

import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as actions from '../actions';
import {push} from 'react-router-redux';

class Test extends Component{
static get propTypes() {
    return { 
      sendContactForm: React.PropTypes.func
    }
  }
        render(){
          return(
            <div</div>
          )
        }
    }

const actionsToProps = {
      deleteFileById: actions.deleteFileById,
      push
    }

export default connect(null, actionsToProps)(Test);

您的代码 App.jsx 应该如下所示

class App extends Component {
    static propTypes = {
        files: PropTypes.array.isRequired,
        isFetching: PropTypes.bool.isRequired,
        deleteFileById : PropTypes.func,
        fetchFiles: PropTypes.func
    };

    componentDidMount() {
       this.props.fetchFiles();
    }

    handleClick = fileId => {
        this.props.deleteFileById(fileId);
    };

    render() {
        const {files, isFetching} = this.props;
        const isEmpty = files.length === 0;
        return (
            <div>
                <h1>Uploadr</h1>
                {isEmpty
                    ? (isFetching ? <h2>Loading...</h2> : <h2>No files.</h2>)
                    : <div style={{opacity: isFetching ? 0.5 : 1}}>
                        <Files files={files} handleClick={this.handleClick}/>
                    </div>
                }
            </div>
        )
    }
}

const mapStateToProps = state => {
    const {isFetching, items: files} = state.files;

    return {
        files,
        isFetching,
    }
};


export default connect(mapStateToProps)(App)

dispatch 应该在actions中返回,而不是从组件到actions,反之亦然

以下是您的参考的示例操作文件。

import ajax from '../ajax';
import {Map, fromJS} from 'immutable';
import config from '../config';
import {push} from 'react-router-redux'

export const URL_PREFIX = 'http://localhost:3000/api';

export const SEND_CONTACT_FORM_REQUEST = 'SEND_CONTACT_FORM_REQUEST';
export const SEND_CONTACT_FORM_SUCCESS = 'SEND_CONTACT_FORM_SUCCESS';
export const SEND_CONTACT_FORM_ERROR = 'SEND_CONTACT_FORM_ERROR';


export function sendContactFormRequest(){
  return {
    type: SEND_CONTACT_FORM_REQUEST,
    loading: true
  }
}

export function sendContactFormSuccess(data){
  return {
    type: SEND_CONTACT_FORM_SUCCESS,
    loading: false,
    data: data
  }
}

export function sendContactFormError(errors){
  return {
    type: SEND_CONTACT_FORM_ERROR,
    loading: false,
    errors: errors
  }
}



export function sendContactForm(firstName, lastName, email, subject, message) {
  return dispatch => {
    dispatch(sendContactFormRequest());
    return ajax.post(URL_PREFIX + '/communication/contact', { firstName, lastName, email, subject, message })
      .then(res => {
        dispatch(sendContactFormSuccess(res.data))


      })
      .catch(errors => {
        dispatch(sendContactFormError(errors))
      })
  }
}

推荐阅读