How to convert the react function into class? - reactjs

I'm used the material-UI to develop the react.js frontend. But when I'm gonna develop it furthermore(to implement the crud operations), it's hard to code, since every tutorial coded by using class, not a function. So, I tried to convert the code into the class. But I failed to do that properly.
So I just ask you guys to help me to convert the below code into the class. I would like to appreciate your kindness. Thank you.
import React from "react";
import ReactDom from 'react-dom';
import Button from '#material-ui/core/Button';
import { Container, Row, Col, Form } from "react-bootstrap";
import TextField from '#material-ui/core/TextField';
import { makeStyles, withStyles } from '#material-ui/core/styles';
const useStyles = makeStyles((theme) => ({
root: {
'& > *': {
margin: theme.spacing(1),
width: '25ch',
},
},
button: {
marginRight: theme.spacing(1),
},
}));
export default function Step2(props) {
const classes = useStyles();
return (
<Container style={{marginRight: 700}}>
<Row
style={{ marginTop: "30px" }}
className="h-100 justify-content-center align-items-center"
>
<Col md={{ span: 6 }} className="text-center my-auto">
<h3 style={{ marginBottom: "1rem" }}>New Vehicle Details</h3>
<Form>
<form className={classes.root} noValidate autoComplete="off">
<TextField id="standard-basic" label="Vehicle No." required/>
</form>
<form className={classes.root} noValidate autoComplete="off">
<TextField id="standard-basic" label="Registered Year." required/>
</form>
<form className={classes.root} noValidate autoComplete="off">
<TextField id="standard-basic" label="Capacity" required/>
</form>
<form className={classes.root} noValidate autoComplete="off">
<TextField id="standard-basic" label="Type" required/>
</form>
<Button
variant="contained"
color="primary"
//onClick={handleNext}
className={classes.button}
>
Add
</Button>
<Button
variant="contained"
color="secondry"
// onClick={handleNext}
className={classes.button}
>
Cancel
</Button>
</Form>
</Col>
</Row>
</Container>
);
}

you are now getting props in parameters of this function just change the function to class.
export default class Step2 extends React.Component {
}
and use props like this.props instead of props

Related

How to loop a component when I click a h3 tag in react using Hooks

According to my question I have one Parent component, it s name is App.js and Child component name is Cardone.js. In Cardone.js component one Card is there. I am passing this Card component as a Child to Parent componet. Now in Parent component I have h3 tag Add One More. What I am trying to achieve is I need to loop a component maximum five times. it should start looping only when I Click h3 tag
This is App.js
import React, { useState } from "react";
import 'antd/dist/antd.css';
import Card from "./Cardone/Cardone"
import { Row, Col } from "antd";
import "./App.css"
const App = () => {
const [comp, loopComp] = useState(<Card></Card>)
const loopComponent = () => {
loopComp(comp + 1)
}
return (
<div>
<Card></Card>
<div style={{display: "flex", justifyContent: "center", marginTop: "10px", cursor: "pointer"}}>
<Row>
<Col span={24}>
<h3 onClick={loopComponent}>Add One More</h3>
</Col>
</Row>
</div>
</div>
)
}
export default App
This is Cardone.js
import React from "react";
import 'antd/dist/antd.css';
import { Card, Form, Input, Button } from 'antd';
import "./Cardone.css";
const Cardone = () => {
// const { Option } = Select;
return (
<div className="site-card-border-less-wrapper">
<div style={{display: "flex", justifyContent: "center", marginTop: "10px"}}>
<Card style={{ width: 900 }}>
<h3>Card One</h3>
<Form layout="inline">
<Form.Item style={{marginTop: "5px"}}
name="firstname"
className="firstname"
rules={[
{
required: true,
message: 'Please enter firstname',
},
]}
>
<Input name="firstname" type="text" placeholder="Enter Firstname" className="firstname" style={{ width: 300 }} />
</Form.Item>
</Form>
<Form layout="inline">
<Form.Item style={{marginTop: "5px"}}
name="lastname"
className="lastname"
rules={[
{
required: true,
message: 'Please enter lasttname',
},
]}
>
<Input name="lasttname" type="text" placeholder="Enter Lastname" className="lastname" style={{ width: 300 }} />
</Form.Item>
</Form>
<Form layout="inline">
<Form.Item style={{marginTop: "5px"}}
name="email"
className="email"
rules={[
{
required: true,
message: 'Please enter email',
},
]}
>
<Input name="email" type="email" placeholder="Enter Email" className="email" style={{ width: 300 }} />
</Form.Item>
</Form>
<Form layout="inline">
<Form.Item style={{marginTop: "5px"}}
name="password"
className="password"
rules={[
{
required: true,
message: 'Please enter password',
},
]}
>
<Input name="password" type="password" placeholder="Enter Password" className="password" style={{ width: 300 }} />
</Form.Item>
</Form>
<Button style={{marginTop: "10px"}} type="primary">Submit</Button>
</Card>,
</div>
</div>
)
}
export default Cardone
you should change App.js like this:
import React, { useState } from "react";
import 'antd/dist/antd.css';
import Card from "./Cardone/Cardone"
import { Row, Col } from "antd";
import "./App.css"
const App = () => {
const [comp, loopComp] = useState([<Card />])
/*** change here***/
const loopComponent = () => {
if(comp.length<5){
comp.push(<Card />);
const newComp = [...comp];
loopComp(newComp);
}
};
/******/
return (
<div>
/*** and change here too***/
{comp.map((m) => m)}
/******/
<div style={{display: "flex", justifyContent: "center", marginTop: "10px", cursor: "pointer"}}>
<Row>
<Col span={24}>
<h3 onClick={loopComponent}>Add One More</h3>
</Col>
</Row>
</div>
</div>
)
}
export default App

Using Material-ui for creating an inline form with label,text, select and button elements (similar to Boostrap)

I am struggling to create an inline form using Material-UI and React which resembles the following
Bootstrap HTML snippet
I created the above using the HTML snippet below. You can try this out at W3Schools.
<div class="container">
<h2>Inline form</h2>
<p>Make the viewport larger than 768px wide to see that all of the form elements are inline, left aligned, and the labels are alongside.</p>
<form class="form-inline" action="/action_page.php">
<div class="form-group">
<label for="sel1">Select search field:</label>
<select class="form-control" id="sel1">
<option>FirstName</option>
<option>LastName</option>
<option>PostCode</option>
<option>Gender</option>
</select>
</div>
<div class="form-group">
<input type="email" class="form-control" id="email" placeholder="Enter search pattern" name="email">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
My attempt using Material-ui
<label htmlFor="selectsearchfield">Select search fields</label>
<span> </span>
<NativeSelect id="selectsearchfield" value={{}}>
<option value="FirstName">FirstName</option>
<option value="LastName">LastName</option>
</NativeSelect>
<span> </span>
<TextField
label="" id="outlined-size-small" defaultValue="" variant="outlined" size="small" disableUnderline />
<span> </span>
<Button size="medium" variant="contained" color="primary">Search</Button>
Question
It can be clearly seen that the output from Bootstrap is far more professional.
Please, any suggestions on how to improve the inline form using Material UI look n feel so that it comes close to Bootstrap.
Thank you,
Sau
You can make use of material-ui makeStyles and make it responsive also:-
import React, { useState } from "react";
import "./style.css";
import classNames from "classnames";
import { makeStyles } from "#material-ui/core/styles";
import {
Button,
FormControl,
OutlinedInput,
TextField,
Typography,
Select,
MenuItem
} from "#material-ui/core";
export default function App() {
const classes = useStyles();
const fields = ["FirstName", "LastName", "PostCode", "Gender"];
const [searcBy, setSearchBy] = useState("FirstName");
const [searchText, setSearchText] = useState("");
return (
<div className={classes.root}>
<form className={classes.form}>
<FormControl className={classNames(classes.formControl, classes.text)}>
<Typography variant="body1" className={classes.type}>
Select search fields:
</Typography>
</FormControl>
<FormControl
className={classNames(classes.formControl, classes.select)}
>
<Select
labelId="typesLabel"
label="Types"
input={<OutlinedInput classes={{ input: classes.input }} />}
value={searcBy}
onChange={e => setSearchBy(e.target.value)}
>
{fields.map(field => (
<MenuItem key={field} value={field}>
{field}
</MenuItem>
))}
</Select>
</FormControl>
<FormControl
className={classNames(classes.formControl, classes.search)}
>
<TextField
label="Enter search pattern"
variant="outlined"
size="small"
value={searchText}
onChange={e => setSearchText(e.target.value)}
/>
</FormControl>
<Button
type="submit"
variant="contained"
color="primary"
className={classes.submitBtn}
>
Primary
</Button>
</form>
</div>
);
}
const useStyles = makeStyles(theme => ({
root: {
display: "flex",
justifyContent: "center",
alignItems: "center"
},
form: {
width: 800,
display: "flex",
flexWrap: "wrap",
justifyContent: "center",
alignItems: "center"
},
container: {
display: "flex",
justifyContent: "center",
alignItems: "center"
},
text: {
minWidth: 120
},
type: {
fontWeight: 600
},
formControl: {
marginRight: theme.spacing(1),
[theme.breakpoints.down("xs")]: {
minWidth: "100%",
marginRight: theme.spacing(0),
marginBottom: theme.spacing(1)
}
},
input: {
padding: "10px 14px"
},
select: {
maxWidth: 130
},
search: {
maxWidth: 180
},
submitBtn: {
[theme.breakpoints.down("xs")]: {
width: "100%"
}
}
}));
Or you can also incorporate the use of Grid from #material-ui/core.Grid instead of using 'flex' like the above example.
Here is the result:-
a bit of explanation of what happened above:-
having input={<OutlinedInput classes={{ input: classes.input }} />} as select element props will enable us to create our own outline instead of depending on the given example code from material-ui select documentation code.
the reason why we do this is since you want to make it exactly as you did with Bootstraps example above. We need to somehow make the select element tad shorter in height. With element TextField, you can just specify size="small". But for select, that option is not available. That's why we have this approach. Or you can directly change the select input element overall styles with withStyles of material-ui/core/styles.
You can also refer to this sandbox code to see the actual working result.

How to invoke a hook from React class component?

Question from React newbie!
I have Material UI React login form and am trying to use hook within login form. But getting invalid hook call error. No luck so far. Help please.. loginformstyles.js is the hook I am trying to use in the signin.js file.. The login page has two text fields - username and password and a Submit button.
import React from 'react';
import Avatar from '#material-ui/core/Avatar';
import Button from '#material-ui/core/Button';
import CssBaseline from '#material-ui/core/CssBaseline';
import TextField from '#material-ui/core/TextField';
import FormControlLabel from '#material-ui/core/FormControlLabel';
import Checkbox from '#material-ui/core/Checkbox';
import Link from '#material-ui/core/Link';
import Grid from '#material-ui/core/Grid';
import Box from '#material-ui/core/Box';
import LockOutlinedIcon from '#material-ui/icons/LockOutlined';
import Typography from '#material-ui/core/Typography';
import Container from '#material-ui/core/Container';
import { ValidatorForm, TextValidator} from 'react-material-ui-form-validator';
import { useStyles } from './loginformstyles';
export default class MyForm extends React.Component {
Copyright() {
return (
<Typography variant="body2" color="textSecondary" align="center">
{'Copyright © '}
<Link color="inherit" href="https://material-ui.com/">
Task Manager
</Link>{' '}
{new Date().getFullYear()}
{'.'}
</Typography>
);
}
handleChange (event) {
const email = event.target.value;
this.setState({ email });
}
render() {
const classes = useStyles();
return (
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<Avatar className={classes.avatar}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Sign in
</Typography>
<form className={classes.form} >
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="email"
label="Email Address"
name="email"
autoComplete="email"
autoFocus
validators={['required', 'isEmail']}
errorMessages={['this field is required', 'email is not valid']}
onChange={this.handleChange}
/>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
/>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
>
Sign In
</Button>
<Grid container>
<Grid item xs>
<Link href="#" variant="body2">
Forgot password?
</Link>
</Grid>
<Grid item>
<Link href="#" variant="body2">
{"Don't have an account? Sign Up"}
</Link>
</Grid>
</Grid>
</form>
</div>
<Box mt={8}>
<this.Copyright />
</Box>
</Container>
);
}
}
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
export const useStyles = makeStyles((theme) => ({
paper: {
marginTop: theme.spacing(8),
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
},
avatar: {
margin: theme.spacing(1),
backgroundColor: theme.palette.secondary.main,
},
form: {
width: '100%', // Fix IE 11 issue.
marginTop: theme.spacing(1),
},
submit: {
margin: theme.spacing(3, 0, 2),
},
}));
If you just want to make this work, you could wrap the it and then expose the styles into child component, ex.
const Wrapper = ({ children }) => {
const classes = useStyles()
return children(classes)
}
and then you can do
<Wrapper>
{classes => <Copyright classes={classes} />}
</Wrapper>
Of course, this is just to get it working. In general you shouldn't mix class and hook, but as long as you can turn them into components, then you can mix and match.

React Material ui - centering item form

i have my my code but i wanna do this i am working with react and material-ui.
What should i change so that my model looks like in the second image?
i am using grid container and item. i must use grid o box?
import React, { Fragment } from 'react';
import Grid from '#material-ui/core/Grid';
import InputAdornment from '#material-ui/core/InputAdornment';
import TextField from '#material-ui/core/TextField';
import PeopleAlt from '#material-ui/icons/PeopleAlt';
import CancelSharpIcon from '#material-ui/icons/CancelSharp';
import Button from '#material-ui/core/Button';
export const Login = () => {
return (
<Grid container direction="column" justify="center" alignItems="center" style={{ height: "200px" }} >
<Grid item> <img src="/logo_ase.png" alt="image" /></Grid>
<form noValidate autoComplete="off">
<div>
<h6>Acceso al sistema</h6>
<TextField
label="usuario"
id="usuario"
InputProps={{
endAdornment: <InputAdornment> <PeopleAlt /> </InputAdornment>
}}
/>
</div>
<div>
<TextField
label="contraseña"
id="contraseña"
type="password"
InputProps={{
endAdornment: <InputAdornment> < CancelSharpIcon /> </InputAdornment>
}}
/>
</div>
<div style={{ padding: 20 }}>
<Button variant="contained" color="primary">Ingresar </Button>
</div>
</form>
</Grid>
);
}
You need to create a div and put your left logo component and Login component inside that. Like this:
<div style={{display: "flex", justifyContent: "center", alignItems: "center"}}>
<Left Component/>
<LoginComponent />
</div>

How to enable file upload on React's Material UI simple input?

I am creating a simple form to upload file using electron-react-boilerplate with redux form & material ui.
The problem is that I do not know how to create input file field because material ui does not support upload file input.
Any ideas on how to achieve this?
The API provides component for this purpose.
<Button
variant="contained"
component="label"
>
Upload File
<input
type="file"
hidden
/>
</Button>
newer MUI version:
<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>
You need to wrap your input with component, and add containerElement property with value 'label' ...
<RaisedButton
containerElement='label' // <-- Just add me!
label='My Label'>
<input type="file" />
</RaisedButton>
You can read more about it in this GitHub issue.
EDIT: Update 2019.
Check at the bottom answer from #galki
TLDR;
<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>
Here's an example using an IconButton to capture input (photo/video capture) using 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);
It is work for me ("#material-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>
If you're using React function components, and you don't like to work with labels or IDs, you can also use a reference.
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>
);
Official recommendation
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>
);
}
Nov 2020
With Material-UI and React Hooks
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>
</>
);
};
You can use Material UI's Input and InputLabel components. Here's an example if you were using them to input spreadsheet files.
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 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>
Just the same as what should be but change the button component to be label like so
<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>
<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>
Make sure Button has component="span", that helped me.
Here an example:
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>
)
Typescript version of #tomatentobi's javascript solution
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>
</>
);
This worked for me.
<Button variant="contained" component="label" >
UPLOAD
<input accept="image/*" hidden type="file" />
</Button>
You can pursue all the comments above, those are really great, However, I have another option for customizing your component, if you want to follow.
// Import
import { styled } from '#mui/material/styles';
import { Input } from "#mui/material";
// Custom style
const CustomFileInput = styled(Input)(({ theme }) => {
return {
color: "white",
'::before': {
border: 'none',
position: 'static',
content: 'none'
},
'::after': {
border: 'none',
position: 'static',
content: 'none'
}
}
});
// Using that component
<CustomFileInput type="file" />
Both #galki and #elijahcarrel method works fine.
If anyone trying to do unit-testing(jest) for these two answers.
You wont be able to use the button component with (specially if you are using disabled=true
expect(getByRole("button", {name: "Upload"})).not.toBeEnabled();
instead use this
expect(getByLabelText("Upload")).not.toBeEnabled();
This is for Select Image File
<IconButton color="primary" component="label">
<input type="file" accept="image/*" hidden />
<AttachFileIcon fontSize="medium" />
</IconButton>
NOTE : React Material UI Component (IconButton, AttachFileIcon)
Or there is library for 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} />
}
Try This
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
or
yarn add mui-file-input
yarn add #mui/icons-material
another way is this and we can add the name of the file as a value for 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>
)
}}
/>

Resources