javascript - 错误:操作必须是普通对象。在删除按钮中使用自定义中间件进行异步操作?
问题描述
在用户从列表中删除文件后,我试图获得一个反应动作来获取文件列表。
在 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)))
};
但是我收到以下错误
错误:操作必须是普通对象。使用自定义中间件进行异步操作。
实现这一点的最佳方法是什么
解决方案
一个动作将调度另一个动作,但不会调度事件处理函数。
您无需从组件中分派 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))
})
}
}
推荐阅读
- javascript - 电子表格.values.get 但与其他工作表
- image - MATLAB图像处理--如何提高寻找圆度算法的准确率?--
- swift - 在 XCTestCase 中读取测试数据时出现“中断的系统调用”
- r - 分类伯努利分布中的GBM错误
- c# - 如何将结构作为函数/方法的参数?
- laravel - Laravel 属于关系获取属性问题
- python - Google Colab 是否有恶意软件?
- python - python浮动一个实数,即使全部为零也保留有效数字
- d3.js - Data Studio 社区可视化中的箱线图代码
- reactjs - ReactJS:使用localStorage保存错误的数据中断最大更新深度超出