关于ant.design中upload组件的setState导致请求中断的问题?

  1. 用ant.design写了一个表单发现上传组件的请求总是被莫名中断,导致图片无法上传。
  2. 调试后发现组件的setSteta({ loading: true })方法导致了组件的unmount,导致了请求的abort
  3. 组件的状态在监听的upload的onchange事件,注释掉onchange事件,问题得以解决
  4. 但是不能再onchange里面改变状态(或者使用redux等状态管理时触发一个action),明显不太合理
  5. 代码如下(其实就是按照官网给的列子写的:https://ant.design/components...),在线demo:https://codesandbox.io/s/wopv...:
import React from 'react';
import ReactDOM from 'react-dom';

import { Upload, Form, Icon } from 'antd';

function getBase64(img, callback) {
    const reader = new FileReader();
    reader.addEventListener('load', () => callback(reader.result));
    reader.readAsDataURL(img);
}

class AddBookForm extends React.Component {
    state = {
        loading: false,
    };

    handleChange = (info) => {
        console.log(info)
        if (info.file.status === 'uploading') {
            this.setState({ loading: true });
            return;
        }
        if (info.file.status === 'done') {
            // Get this url from response in real world.
            getBase64(info.file.originFileObj, imageUrl => this.setState({
                imageUrl,
                loading: false,
            }));
        }
    }

    render() {
        const formItemLayout = { labelCol: { xs: 24, sm: 2 }, wrapperCol: { xs: 24, sm: 8 } };
        const FormItem = function(props) {
            return <Form.Item {...formItemLayout} {...props}></Form.Item>;
        };
        const uploadButton = (
            <div>
                <Icon type={this.state.loading ? 'loading' : 'plus'} />
                <div className="ant-upload-text">Upload</div>
            </div>
        );
        const imageUrl = this.state.imageUrl;

        return (
            <Form layout="horizontal">
                <FormItem label="图片" extra="请上传2M以内的JPG图片">
                        <Upload
                            name='imageFile'
                            action="/api/image-upload"
                            onChange={this.handleChange}
                            showUploadList={false}
                            listType="picture-card"
                            className="single-image-uploader"
                        >
                            {imageUrl ? <img src={imageUrl} alt="" /> : uploadButton}
                        </Upload>
                </FormItem>
            </Form>
        );
    }
}

ReactDOM.render((
    <AddBookForm />
), document.getElementById('root'));

这个问题已经困扰了我非常久的时间,请各位大神指导一下如何解决这个问题。

阅读 5.9k
2 个回答

每一次onChange都要执行setState。
参考

题主我和你遇到了同样的问题。但是不清楚你的具体需求,我简单说下我的具体需求以及遇到的问题以及解决方案。
1.首先我想要使用setState的缘由是,antd uoload组件默认action请求地址,这就涉及到传参问题。对应上传文件的同时要传参那么就涉及地址拼接;

2.然后我再action的请求地址后拼接了需要传递的参数,也就是这样:

clipboard.png

3.然而当前id是通过点击对应的列表数据然后传递id来实时对应上传文件,此时涉及到setState({id}),我分别将请求放在组件默认方法onchange,beforeUpdate中来更新id,结果并未如愿。也就是出现题主所说,setstate更新导致组将重新渲染上传中断的问题。

4.接下来想到将state作为普通遍历存储然后赋值,最后将变量发在地址后拼接。结果如下:

clipboard.png
事实上并没有拿到所需的最新的id,然后分析发现action是个常量,初始化时刻我们变量为空,之后的变量值变化并不会影响action的值,so拿不到所需id,于是继续分析...

5.于是乎分析到组件的上传方式应该是post上传

clipboard.png
此时,问题的关键来了,网络请求post方法是不会用地址拼接参数的。于是再antd官方文档找到对应的api

clipboard.png

clipboard.png

data方法传递参数,才是正解,最终绕过了数据更新导致组件重新渲染组件上传中断的问题。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题