一文搞懂react upload上传组件

3,807 阅读3分钟

介绍

很多APP都会有上传图片或者文件的功能,对于创建一个全栈的APP这是很基础的需求。比如Facebook、Instagram和Snapchat都有上传图片和视频的能力。

在传统的HTML网站,上传文件表单会强制页面刷新,用户可能会感到奇怪。同时,你可能也会想要定制上传表单的样式能和你的APP的整体设计风格保持一致。当谈到这些问题的时候,React可以帮助你提供一个更好的用户体验。这篇指南可以帮助你建立并运行一个包含文件上传的React应用。

创建基础表单

可以参考React官方指南,创建一个React应用,在App.js 中创建一个简单的表单,包含一个name字段和一个文件输入字段。如下:


import React from "react";

const App = () => {

  return (

    <div className="App">

      <form>

        <input type="text" />

        <input type="file" />

      </form>

    </div>

  );

};

然后在组件中增加state用来存储name字段和文件数据。


import React, { useState } from "react";

const App = () => {

  const [name, setName] = useState("");

  const [selectedFile, setSelectedFile] = useState(null);

  return (

    <div className="App">

      <form>

        <input

          type="text"

          value={name}

          onChange={(e) => setName(e.target.value)}

        />

        <input

          type="file"

          value={selectedFile}

          onChange={(e) => setSelectedFile(e.target.files[0])}

        />

      </form>

    </div>

  );

};

封装自定义上传组件

既然基本的表单已经创建好了,接下来我们可以封装一个自定义的文件上传组件方便后面可以在app中复用到不同的场景。如果你在网页上查看这个表单,你可能会觉得外观并不是那么好看,那是因为浏览器应用的是默认的样式。本节我们将介绍如何创建一个自定义样式的上传组件。


const FileUploader = () => {

    const handleFileInput = () => {}

    return (

        <div className="file-uploader">

            <input type="file" onChange={handleFileInput}>

        </div>

    )

}

为了创建一个自定义文件上传组件,第一步是隐藏默认的输入框,通过ref来触发输入框的click事件


import React, {useRef} from 'react'

const FileUploader = ({onFileSelect}) => {

    const fileInput = useRef(null)

    const handleFileInput = (e) => {

        // handle validations

        onFileSelect(e.target.files[0])

    }

    return (

        <div className="file-uploader">

            <input ref="fileInput" type="file" onChange={handleFileInput}>

            <button onClick={e => fileInput.current && fileInput.current.click()} className="btn btn-primary">

        </div>

    )

}

你可以给上传按钮增加和你整理应用匹配的样式,将上传的文件通过onchange回调函数回传给父组件函数onFileSelect。在handleFileInput方法中,你还可以增加校验函数,比如校验文件大小,文件扩展名等等。然后可以回调父组件通过pros透传的处理函数onFileSelectSuccess和onFileSelectError等。


const handleFileInput = (e) => {

  // handle validations

  const file = e.target.files[0];

  if (file.size > 1024)

    onFileSelectError({ error: "File size cannot exceed more than 1MB" });

  else onFileSelectSuccess(file);

};

将上传组件添加到表单

将表单引入上传组件,如下:


import React, { useState } from "react";

const App = () => {

  const [name, setName] = useState("");

  const [selectedFile, setSelectedFile] = useState(null);

  const submitForm = () => {};

  return (

    <div className="App">

      <form>

        <input

          type="text"

          value={name}

          onChange={(e) => setName(e.target.value)}

        />

        <FileUploaded

          onFileSelectSuccess={(file) => setSelectedFile(file)}

          onFileSelectError={({ error }) => alert(error)}

       />

        <button onClick={submitForm}>Submit</button>

      </form>

    </div>

  );

};

通过FormData上传文件

可以通过FormData对象来上传文件,通过append方法在FormData对象中追加name和file字段数据。


const submitForm = () => {

  const formData = new FormData();

  formData.append("name", name);

  formData.append("file", selectedFile);


  axios

    .post(UPLOAD_URL, formData)

    .then((res) => {

      alert("File Upload success");

    })

    .catch((err) => alert("File Upload Error"));

};

好了,这里你已经成功的创建了一个自定义上传组件的表单了。

总结

文件上传是web应用的基本功能,你可以使用第三方的类库来实现自定义文件上传,但是你应该有基础的认知了解这些组件的实现原理。当你遇到一些三方组件没办法实现的定制上传场景时,自己定义的上传组件或许能够帮你实现。