Formik:将文件上传为formData不能与Redux一起使用

时间:2019-05-16 17:53:53

标签: reactjs redux redux-saga formik

我正在尝试使用redux-saga和formik做一个简单的文件上传,以处理我的表单。

服务器不断返回400 error(无效输入),我的服务器需要具有属性formData的{​​{1}}对象。

这是我使用Formik的表格:

file

我正在使用Ant Design中的自定义上载组件,当新文件已被上载并将其正确添加到 <Formik initialValues={{ file: null }} validationSchema={CreateWorkspaceSchema} onSubmit={(values: FormikValues, { resetForm }: FormikActions<FormikValues>) => { resetForm({}) onSubmit(values) }} > {({ values, errors, touched, handleChange, handleSubmit, setFieldValue }) => <Modal title="Create a workspace" visible={showModal} onOk={handleSubmit} okButtonProps={{ htmlType: "submit" }} onCancel={onShowModal} okText='Create' > <Spin spinning={status === ProgressStatus.InProgress}> {message ? <Alert type="error" closable message={message} showIcon style={{ marginBottom: "10px" }} /> : null} <Form onSubmit={handleSubmit}> <Upload beforeUpload={() => false} multiple={false} name="file" listType="picture" onChange={(event) => { setFieldValue("file", event.fileList[0]); }}> <Button> <Icon type="upload" /> Upload image </Button> </Upload> </Form> </Spin> </Modal> } </Formik>

时,onChange将启动

我的formikValues负责启动我的onSubmit操作:

redux-saga

我的传奇:

onCreateWorkspace = (values: FormikValues) => {
    const { user, createWorkspace } = this.props;
    createWorkspace(Object.assign(
        values,
        {
            owner: `api/users/${user.id}`
        }
    ) as CreateWorkspaceValues)
}

我尝试添加以下标头:

const formData = new FormData();
formData.append('file', action.payload.file)

const fileResponse = yield call(
  fetch,
  `${api.url}/api/media_objects`,
  {
    method: 'POST',
    body: formData
  }
);
return console.log(fileResponse);

但是错误仍然保持不变。

我尝试在Postman中进行相同的操作,以查看我的后端服务器是否出了点问题,但是在postman中上传的文件可以正常工作。我在邮递员中上传的内容如下:

enter image description here

我在这里想念什么?

1 个答案:

答案 0 :(得分:0)

前段时间我也遇到过同样的问题,而且似乎解决方案“简单”但难以理解,因为道具的流动不是很明显(至少对我而言)。我将尽可能简单地描述如何设法通过redux-saga上传文件的概述:

首先,为了将我们的Formik组件与redux连接起来,我们需要用HOC包装它。可以使用withFormik() API来完成此操作,

import { connect } from 'react-redux';
import { withFormik } from 'formik';
import Demo from './Demo'; // <--- the form component to be upgraded using this HOC
import * as types from './types';

const Form = withFormik({
    handleSubmit: (values, { props }) => {
        props.uploadFile(values); // <<--- Some action passed down from redux connect
    }
})(Demo);

const mapStateToProps = state => ({
    uploading: state.uploading
});

const mapDispatchToProps = dispatch => ({
    uploadFile: (
        values // <<-- Here's where the action is passed down
    ) =>
        dispatch({
            type: types.UPLOAD_FILE_REQUEST,
            payload: values
        })
});

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

第二,既然我们已经升级了Formik组件,则可以进行dispatch动作并在其中使用我们的商店。

最后,为了上传文件,我们可以使用redux-saga如下:

import { put, takeLatest } from 'redux-saga/effects';
import * as types from './types';
import reqwest from 'reqwest';
import { message } from 'antd';

function* uploadFileSaga({ formData }) {
    try {
        // You can use any AJAX library you like
        const request = yield reqwest({
            url: 'https://www.mocky.io/v2/5cc8019d300000980a055e76',
            method: 'post',
            processData: false,
            data: formData,
            success: () => {
                message.success('upload successfully.');
            },
            error: () => {
                message.error('upload failed.');
            }
        });
        if (request.status === 'done') {
            yield put({ type: types.UPLOAD_FILE_SUCCESS });
        }
    } catch (e) {
        console.log(e);
    }
}

export default function* rootSaga() {
    yield takeLatest(types.UPLOAD_FILE_REQUEST, uploadFileSaga);
}

此传奇使用reqwest处理AJAX调用(与Ant-Design所使用的相同)。尽管您可以选择要使用的任何库。

您可以进入此sandbox并观看完整的演示以及它如何与Ant-Design一起工作。