如何使文件上传反应的材料用户界面简单输入?

我正在创建一个简单的形式上传文件使用电子反应样板与还原形式和材料 UI。

问题是,我不知道如何创建输入文件字段,因为材料 ui 不支持上传文件输入。

对于如何实现这一点有什么想法吗?

281514 次浏览

您需要用 组件包装您的输入,并用 价值’标签’添加 集装箱元素属性..。

<RaisedButton
containerElement='label' // <-- Just add me!
label='My Label'>
<input type="file" />
</RaisedButton>

您可以在这个 GitHub 问题中了解更多信息。

编辑: 更新2019。

检查从 @ galki的底部答案

极低密度辐射;

<input
accept="image/*"
className={classes.input}
style=\{\{ display: 'none' }}
id="raised-button-file"
multiple
type="file"
/>
<label htmlFor="raised-button-file">
<Button variant="raised" component="span" className={classes.button}>
Upload
</Button>
</label>

更新的 MUI 版本:

<input
accept="image/*"
className={classes.input}
style=\{\{ display: 'none' }}
id="raised-button-file"
multiple
type="file"
/>
<label htmlFor="raised-button-file">
<Button variant="raised" component="span" className={classes.button}>
Upload
</Button>
</label>

API 为此提供了 component

<Button
variant="contained"
component="label"
>
Upload File
<input
type="file"
hidden
/>
</Button>

下面是一个使用 IconButton 使用 v3.9.2捕获输入(照片/视频捕获)的例子:

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


import { withStyles } from '@material-ui/core/styles';
import IconButton from '@material-ui/core/IconButton';
import PhotoCamera from '@material-ui/icons/PhotoCamera';
import Videocam from '@material-ui/icons/Videocam';


const styles = (theme) => ({
input: {
display: 'none'
}
});


class MediaCapture extends Component {
static propTypes = {
classes: PropTypes.object.isRequired
};


state: {
images: [],
videos: []
};


handleCapture = ({ target }) => {
const fileReader = new FileReader();
const name = target.accept.includes('image') ? 'images' : 'videos';


fileReader.readAsDataURL(target.files[0]);
fileReader.onload = (e) => {
this.setState((prevState) => ({
[name]: [...prevState[name], e.target.result]
}));
};
};


render() {
const { classes } = this.props;


return (
<Fragment>
<input
accept="image/*"
className={classes.input}
id="icon-button-photo"
onChange={this.handleCapture}
type="file"
/>
<label htmlFor="icon-button-photo">
<IconButton color="primary" component="span">
<PhotoCamera />
</IconButton>
</label>


<input
accept="video/*"
capture="camcorder"
className={classes.input}
id="icon-button-video"
onChange={this.handleCapture}
type="file"
/>
<label htmlFor="icon-button-video">
<IconButton color="primary" component="span">
<Videocam />
</IconButton>
</label>
</Fragment>
);
}
}


export default withStyles(styles, { withTheme: true })(MediaCapture);

这是我的工作(“@Materials-ui/core”: “ ^ 4.3.1”) :

    <Fragment>
<input
color="primary"
accept="image/*"
type="file"
onChange={onChange}
id="icon-button-file"
style=\{\{ display: 'none', }}
/>
<label htmlFor="icon-button-file">
<Button
variant="contained"
component="span"
className={classes.button}
size="large"
color="primary"
>
<ImageIcon className={classes.extendedIcon} />
</Button>
</label>
</Fragment>

就像应该是什么一样,但是改变按钮组件为标签,如下所示

<form id='uploadForm'
action='http://localhost:8000/upload'
method='post'
encType="multipart/form-data">
<input type="file" id="sampleFile" style="display: none;" />
<Button htmlFor="sampleFile" component="label" type={'submit'}>Upload</Button>
</form>

如果您正在使用 React 函数组件,并且不喜欢使用标签或 ID,那么还可以使用引用。

const uploadInputRef = useRef(null);


return (
<Fragment>
<input
ref={uploadInputRef}
type="file"
accept="image/*"
style=\{\{ display: "none" }}
onChange={onChange}
/>
<Button
onClick={() => uploadInputRef.current && uploadInputRef.current.click()}
variant="contained"
>
Upload
</Button>
</Fragment>
);
<input type="file"
id="fileUploadButton"
style=\{\{ display: 'none' }}
onChange={onFileChange}
/>
<label htmlFor={'fileUploadButton'}>
<Button
color="secondary"
className={classes.btnUpload}
variant="contained"
component="span"
startIcon={
<SvgIcon fontSize="small">
<UploadIcon />
</SvgIcon>
}
>


Upload
</Button>
</label>

确保 Button 具有 Component = “ span” ,这对我有帮助。

可以使用 Materials UI 的 Input 和 InputLabel 组件。这里有一个例子,如果您使用它们来输入电子表格文件。

import { Input, InputLabel } from "@material-ui/core";


const styles = {
hidden: {
display: "none",
},
importLabel: {
color: "black",
},
};


<InputLabel htmlFor="import-button" style={styles.importLabel}>
<Input
id="import-button"
inputProps=\{\{
accept:
".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel",
}}
onChange={onInputChange}
style={styles.hidden}
type="file"
/>
Import Spreadsheet
</InputLabel>

二零二零年十一月

用材质-用户界面和反应挂钩

import * as React from "react";
import {
Button,
IconButton,
Tooltip,
makeStyles,
Theme,
} from "@material-ui/core";
import { PhotoCamera } from "@material-ui/icons";


const useStyles = makeStyles((theme: Theme) => ({
root: {
"& > *": {
margin: theme.spacing(1),
},
},
input: {
display: "none",
},
faceImage: {
color: theme.palette.primary.light,
},
}));


interface FormProps {
saveFace: any; //(fileName:Blob) => Promise<void>, // callback taking a string and then dispatching a store actions
}


export const FaceForm: React.FunctionComponent<FormProps> = ({ saveFace }) => {


const classes = useStyles();
const [selectedFile, setSelectedFile] = React.useState(null);


const handleCapture = ({ target }: any) => {
setSelectedFile(target.files[0]);
};


const handleSubmit = () => {
saveFace(selectedFile);
};


return (
<>
<input
accept="image/jpeg"
className={classes.input}
id="faceImage"
type="file"
onChange={handleCapture}
/>
<Tooltip title="Select Image">
<label htmlFor="faceImage">
<IconButton
className={classes.faceImage}
color="primary"
aria-label="upload picture"
component="span"
>
<PhotoCamera fontSize="large" />
</IconButton>
</label>
</Tooltip>
<label>{selectedFile ? selectedFile.name : "Select Image"}</label>. . .
<Button onClick={() => handleSubmit()} color="primary">
Save
</Button>
</>
);
};


举个例子:

return (
<Box alignItems='center' display='flex' justifyContent='center' flexDirection='column'>
<Box>
<input accept="image/*" id="upload-company-logo" type='file' hidden />
<label htmlFor="upload-company-logo">
<Button component="span" >
<Paper elevation={5}>
<Avatar src={formik.values.logo} className={classes.avatar} variant='rounded' />
</Paper>
</Button>
</label>
</Box>
</Box>
)


你可以继续上面的所有评论,那些真的很棒,但是,我有另一个选项来定制您的组件,如果你想遵循。

//进口

import { styled } from '@mui/material/styles';
import { Input } from "@mui/material";

//自订风格

const CustomFileInput = styled(Input)(({ theme }) => {
return {
color: "white",
'::before': {
border: 'none',
position: 'static',
content: 'none'
},
'::after': {
border: 'none',
position: 'static',
content: 'none'
}
}
});

//使用该组件

<CustomFileInput type="file" />

@ galki 和@elijahcarrel 方法都很好用。 如果有人试图对这两个答案进行单元测试(开玩笑)。

您不能使用带有 < code > 的按钮组件(特别是如果您正在使用  禁用 = true

expect(getByRole("button", {name: "Upload"})).not.toBeEnabled();

而不是用这个

expect(getByLabelText("Upload")).not.toBeEnabled();

官方推荐

import * as React from 'react';
import { styled } from '@mui/material/styles';
import Button from '@mui/material/Button';
import IconButton from '@mui/material/IconButton';
import PhotoCamera from '@mui/icons-material/PhotoCamera';
import Stack from '@mui/material/Stack';


const Input = styled('input')({
display: 'none',
});


export default function UploadButtons() {
return (
<Stack direction="row" alignItems="center" spacing={2}>
<label htmlFor="contained-button-file">
<Input accept="image/*" id="contained-button-file" multiple type="file" />
<Button variant="contained" component="span">
Upload
</Button>
</label>
<label htmlFor="icon-button-file">
<Input accept="image/*" id="icon-button-file" type="file" />
<IconButton color="primary" aria-label="upload picture" component="span">
<PhotoCamera />
</IconButton>
</label>
</Stack>
);
}
 import AddPhotoIcon from "@mui/icons-material/AddAPhoto";
import Fab from "@mui/material/Fab";


<Fab color="primary" aria-label="add-image" sx=\{\{ position: "fixed", bottom: 16, right: 16, overflow: "hidden" }}>
<input
type="file"
onChange={imageHandler}
accept=".jpg, .jpeg, .png"
accept="image/*"
multiple
style=\{\{ //make this hidden and display only the icon
position: "absolute",
top: "-35px",
left: 0,
height: "calc(100% + 36px)",
width: "calc(100% + 5px)",
outline: "none",
}}
/>


<AddPhotoIcon />
</Fab>

这是用于选择图像文件

<IconButton color="primary" component="label">
<input type="file" accept="image/*" hidden />
<AttachFileIcon fontSize="medium" />
</IconButton>

注意: < em > React Materials UI Component (IconButton,AttachFileIcon)

另一种方法是这样,我们可以添加文件名作为 TextField的值。

<TextField
value={state.value}
label="upload profile picture"
sx=\{\{ m: 1, width: '25ch' }}
InputProps=\{\{
fullWidth: true,
startAdornment: (
<IconButton component="label">
<AttachFileIcon />
<input
type="file"
hidden
onChange={handleUploadInput}
name="[name]"
/>
</IconButton>
)
}}
/>

@ tomatentobi 的 javascript 解决方案的打字稿版本

const uploadInputRef = useRef<HTMLInputElement | null>(null);


return (
<>
<input
ref={uploadInputRef}
type="file"
accept="image/*"
style=\{\{ display: "none" }}
onChange={onChange}
/>
<Button
onClick={() => uploadInputRef.current && uploadInputRef.current.click()}
variant="contained">
Upload
</Button>
</>
);

或者有一个 MUI 5/React 18: https://viclafouch.github.io/mui-file-input/的库

import React from 'react'
import { MuiFileInput } from 'mui-file-input'


const MyComponent = () => {
const [value, setValue] = React.useState(null)


const handleChange = (newValue) => {
setValue(newValue)
}


return <MuiFileInput value={value} onChange={handleChange} />
}

试试这个

enter image description here enter image description here

import React from 'react'
import { MuiFileInput } from 'mui-file-input'


export default function MyComponent () {
const [file, setFile] = React.useState(null)


const handleChange = (newFile) => {
setFile(newFile)
}


return (
<MuiFileInput value={file} onChange={handleChange} />
)
}
npm install mui-file-input --save
npm install @mui/icons-material

或者

yarn add mui-file-input
yarn add @mui/icons-material