ref value undefined ReactJs - reactjs

i Used material Design For my login From but when i get console.log in onsubmitForm show ref value undefined...
In the following simple example, both this.UserEmail.value & this.UserPassword.value are undefined when the submit is clicked.
export default class SignIn extends React.Component {
UserEmail= null;
UserPassword=null;
onsubmitForm = (e) =>
{
e.preventDefault();
let EmailData = this.UserEmail.value;
let PassData = this.UserPassword.value;
let data = {EmailData,PassData}
console.log("this is the submit form function");
console.log(data); // I Get Data Obj Undefined
}
render(){
return (
<div>
<form>
<TextField
variant="outlined"
margin="normal"
required
ref={el => this.UserEmail = el}
id="email"
label="Email"
name="email"
autoComplete="email"
autoFocus
/>
<TextField
variant="outlined"
margin="normal"
fullWidth
ref={el => this.UserPassword = el}
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>
<Button
type="submit"
onClick={this.onsubmitForm}
variant="contained"
color="primary"
>
Login
</Button>
</form>
</div>
);
}
}

The value of the ref is undefined because for Material-UI's API requires that you use inputRef instead of ref to access the input elements inside the nested components.
export default class SignIn extends React.Component {
onsubmitForm = e => {
e.preventDefault();
const email = this.email.value;
const password = this.password.value;
let data = { email, password };
console.log("this is the submit form function");
console.log(data);
};
render() {
return (
<div>
<form>
<TextField
variant="outlined"
margin="normal"
required
inputRef={email => (this.email = email)}
id="email"
label="Email"
name="email"
autoComplete="email"
autoFocus
/>
<TextField
variant="outlined"
margin="normal"
fullWidth
inputRef={password => (this.password = password)}
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>
<Button
type="submit"
onClick={this.onsubmitForm}
variant="contained"
color="primary"
>
Login
</Button>
</form>
</div>
);
}
}
Working example here

Related

How can I set the textfield as disabled and when typed, it will be enabled again?

How can I code this where the textfield's original state will be disabled and then when typed in, it will be enabled. Then that textfield will be the only one be updated when submitted?
<form onSubmit={handleSubmit}>
<TextField
id="input"
margin="dense"
type="text"
label="Name"
placeholder={user.displayName}
value={displayName}
fullWidth
onChange={(e) => setdisplayName(e.target.value)}
/>
<TextField
disabled
margin="dense"
type="text"
label="address"
value={address}
fullWidth
onChange={(e) => setAddress(e.target.value)}
/>
<Button type="submit">Update</Button>
</form>
Even though you disable one input, It still re-render everytime you typing (because you setState on change). You can use ref like this to prevent unnecessary render.
const nameRef = useRef(null);
const addressRef = useRef(null);
const handleSubmit = (e) => {
e.preventDefault();
console.log(nameRef.current.value);
console.log(addressRef.current.value);
};
return (
<div>
<form onSubmit={handleSubmit}>
<TextField
id="input"
margin="dense"
type="text"
label="Name"
placeholder={user.displayName}
fullWidth
inputRef={nameRef}
/>
<TextField
margin="dense"
type="text"
label="address"
fullWidth
inputRef={addressRef}
/>
<Button type="submit">Update</Button>
</form>
)
You can add a validation on handleSubmit because if a textfield is disabled, you need another action to make it enable and it's not ok for the user also.
You can try to add something like:
const handleSubmit = () => {
if ((displayName === "" || displayName == null) && (address == "" || address === null) {
//show error for user that both fields have to be completed
} else {
//do the form submit
}
}

How to clear input fields after submit in react

so i'm creating my portfolio and i am now on the final page, the contact page. I have it almost finished. I have it hooked up with emailjs and i receive emails with the message inputted as expected.
The problem i'm having is, when the form is submitted, i don't know how to clear the UI input fields. I could disregard using e.preventDefault(), however, i would like to keep that, as i want to style the page if the desired result has been achieved(message sent), or if an error has occurred. I would like to mention that i had used state for the name, email and message beforehand, however, i was unable to use the state variables in conjunction with the emailjs syntax, more specifically, with the "e.target" section. When the form is submitted, the result is the message being sent to my email, with the text inputted by the user still in the input fields.
The code is below, with some names left as hidden for privacy reasons:
import React, { useState } from 'react'
import { Box, Grid, Typography, Button} from '#material-ui/core'
import Navbar from './Navbar';
import Styles, { InputField } from './Styles'
import SendIcon from '#material-ui/icons/Send'
import emailjs from 'emailjs-com'
function Contact() {
const classes = Styles()
function sendEmail(e) {
e.preventDefault()
emailjs.sendForm('gmail', 'hidden', e.target, 'hidden')
.then((result) => {
console.log(result.text);
result.text ==="OK" ? console.log("it worked") : console.log("didnt work")
}, (error) => {
console.log(error.text);
});
}
return (
<Box component='div'>
<Navbar/>
<Grid container justify='center'>
<Box component='form' className={classes.contactContainer} onSubmit={sendEmail}>
<Typography variant='h5' className={classes.contactHead}>Contact Me</Typography>
<InputField
id="name"
name="name"
fullWidth={true}
label="Name"
variant="outlined"
margin='dense'
size='medium'
/>
<br/>
<InputField
id="email"
name="email"
fullWidth={true}
label="Email"
variant="outlined"
margin='dense'
size='medium'
/>
<br/>
<InputField
id="message"
name="message"
fullWidth={true}
label="Enter Message Here"
multiline
rows={8}
variant="outlined"
margin='dense'
size='medium'
/>
<br/>
<Button
type="submit"
variant='outlined'
fullWidth={true}
endIcon={<SendIcon/>}
className={classes.contactButton}>
Contact Me
</Button>
</Box>
</Grid>
</Box>
)
}
export default Contact
For the simplest way to do it in your code, use useState to declare initial value of the fields such as:
const [name, setName] = useState("");
Then you need to set the "value" param in your InputField component, eg:
<InputField
id="name"
name="name"
fullWidth={true}
label="Name"
variant="outlined"
margin='dense'
size='medium'
value={name}
/>
And after receiving the result in emailjs.sendForm, use setName to reset the value of the name field, eg:
setName("")
Use the similar method for other fields.
Thank you for the answer, it helped, however did not fully fix the problem. That being said, i was able to find a solution. I used the onChange param and passed through a function which changes the state AND the value. Also, after receiving the result in emailjs.sendForm, i reset the value of all the fields.
const handleChange = (event) => {
event.target.name=="name"
? setName(event.target.value)
: event.target.name=="email"
? setEmail(event.target.value)
: event.target.name=="message"
? setMessage(event.target.value)
: console.log("error")
};
function sendEmail(e) {
e.preventDefault()
emailjs.sendForm('gmail', 'hiddenForPrivacy', e.target, 'hiddenForPrivacy')
.then((result) => {
console.log(result.text);
result.text ==="OK" ? console.log("it worked") : alert("didnt work")
setName("")
setMessage("")
setEmail("")
}, (error) => {
console.log(error.text);
});
}
The input fields now look like this:
return (
<Box component='div'>
<Navbar/>
<Grid container justify='center'>
<Box component='form' className={classes.contactContainer} onSubmit={sendEmail}>
<Typography variant='h5' className={classes.contactHead}>Contact Me</Typography>
<InputField
id="name"
name="name"
fullWidth={true}
label="Name"
variant="outlined"
margin='dense'
size='medium'
onChange={(e) => handleChange(e)}
value={name}
/>
<br/>
<InputField
id="email"
name="email"
fullWidth={true}
label="Email"
variant="outlined"
margin='dense'
size='medium'
onChange={(e) => handleChange(e)}
value={email}
/>
<br/>
<InputField
id="message"
name="message"
fullWidth={true}
label="Enter Message Here"
multiline
rows={8}
variant="outlined"
margin='dense'
size='medium'
onChange={(e) => handleChange(e)}
value={message}
/>
<br/>
<Button
type="submit"
variant='outlined'
fullWidth={true}
endIcon={<SendIcon/>}
className={classes.contactButton}>
Contact Me
</Button>
</Box>
</Grid>
</Box>

Why button's onClick event is triggered when i typing in TextField ReactJS

I have a sample code for Signing page as follows, When I am typing the username and passwords inside the text fields with every character the onClick event of the button is triggered and I can see the output of console.log(). Why it is triggered?
class Signin extends React.Component {
state = {
username: null,
password: null,
}
render () {
const { t, classes } = this.props;
return (
<div >
<div >
<div >
<Card>
<CardContent>
<form>
<TextField
inputProps={{ style:{fontSize:20, textAlign:'center', direction:'ltr'} }}
value={this.state.username}
onChange={e => this.setState({username: e.target.value})}
id="username"
label={t("Username")}
className={classes.textField}
fullWidth
margin="normal"
/>
<TextField
inputProps={{ style:{fontSize:20, textAlign:'center', direction:'ltr'} }}
value={this.state.password}
onChange={e => this.setState({password: e.target.value})}
id="password"
label={t("Password")}
className={classes.textField}
type="password"
fullWidth
margin="normal"
/>
<Button variant="raised" color="primary" fullWidth type="submit" onClick={console.log(this.state.username,this.state.password)} >{t("Login")}</Button>
</form>
</CardContent>
</Card>
</div>
</div>
</div>
);
}
}
Change your console.log from:
onClick={console.log(this.state.username,this.state.password)}
to like this below:
onClick={() => console.log(this.state.username,this.state.password)}
try this
it is happening because It depends on where exactly are you using the Arrow function. If the Arrow function is used in the render method, then they create a new instance every time render is called just like how bind would work.
<Button
variant="raised"
color="primary"
fullWidth type="submit"
onClick={()=>{console.log(this.state.username,this.state.password)} >{t("Login")}}</Button>

How to get input value of TextField from Material UI without using onChange event?

I tried to use this.refs.myField.getValue() or this.refs.myTextField.input.value. But, they are depreciated.
I don't want to use onChange inside TextField, I just convert the text when clicking button Convert
import React from 'react';
import TextField from '#material-ui/core/TextField';
import Button from '#material-ui/core/Button';
class Test extends React.Component {
constructor(props) {
super(props);
this.state = {
text: '',
};
};
handleConvertString = (event) => {
let str = this.refs.myField.getValue();
this.setState({
text: str.replace(/[dog]/gi, ''),
})
};
render() {
return (
<div>
<TextField
ref="myField"
fullWidth
/>
<Button variant="outlined" href="#outlined-buttons" onClick={this.handleConvertString}>
Convert
</Button>
<h1>{this.state.text}</h1>
</div>
)
}
}
export default Test;
Take a look at the MUI text field API docs.
You are trying to access the underlying value of the text area, so you need the ref of the HTML DOM element.
For the text area, use:
<TextField
inputRef={ref => { this.inputRef = ref; }}
fullWidth
/>
And then in your method access the value with this.inputRef.value.
const { register, handleSubmit } = useForm();
<form onSubmit={handleSubmit(formSubmit)}>
<label>
<TextField
id="outlined-basic"
label="email"
name="email"
fullWidth
variant="outlined"
inputRef={register}
required
/>
</label>
<br />
<label>
<br />
<TextField
id="outlined-secondary:cyan"
label="password"
name="password"
type="password"
fullWidth
variant="outlined"
inputRef={register}
required
/>
</label>
<br />
<br />
<Button
className={classes.root}
variant="contained"
color="primary"
fullWidth
type="submit"
>
Login
</Button>
</form>
Then handling it with :
const formSubmit = (data) => {
// Post Data
const postData = {
email: data.email,
pass: data.password,
};
console.log(data)

How to add event handlers within const in React?

I'm new to React and I'm doing a react project with PRIMER React template. In the sign in page, the code as follows.
const Signin = (props) => {
const { classes } = props;
return (
<form>
<TextField
id="username"
label="Username"
className={classes.textField}
fullWidth
margin="normal"
/>
<TextField
id="password"
label="Password"
className={classes.textField}
type="password"
fullWidth
margin="normal"
/>
<Button variant="raised" color="primary" fullWidth type="submit">Login</Button>
</form>
);
}
I need to add the form Submit event handler. So I added that code as follows.
const Signin = (props) => {
const { classes } = props;
this.handleSubmit = this.handleSubmit.bind(this);
handleSubmit(event) {
event.preventDefault();
const data = new FormData(event.target);
this.setState({
res: data
});
console.log(this.state.res)
}
return (
<form onSubmit={this.handleSubmit}>
<TextField
id="username"
label="Username"
className={classes.textField}
fullWidth
margin="normal"
/>
<TextField
id="password"
label="Password"
className={classes.textField}
type="password"
fullWidth
margin="normal"
/>
<Button variant="raised" color="primary" fullWidth type="submit">Login</Button>
</form>
);
}
But this is not working. I can't even compile this. Whats the wrong here and How can I manage event handlers??
Your component is a functional component. So do the followings and run once :
remove this.handleSubmit = this.handleSubmit.bind(this);
event handleSubmit place it like a const handleSubmit = (e) => {} or place it outside the component and setState - make it as a class component.Still you need functional component, use hooks or use refs inside stateless components.
change <form onSubmit={this.handleSubmit}> to <form onSubmit={handleSubmit}>
Either, you can use class component for this case Signin if your intention is to use setState. to Converting a Function to a Class check this.
and in functional component you can define ref like this:
<input type='text' placeholder='Enter City Name'
ref={ el => cityInput = el } />
and in submit you can get it's value like:
cityInput.value
Example Functoinal Component :
const MyComponent = (props) => {
let cityInput
const onSubmit = e => {
e.preventDefault()
let city = cityInput.value
if (city) {
console.log(city)
}
}
return (
<div>
<form onSubmit={ onSubmit }>
<div>
<input type='text' placeholder='Enter City Name'
ref={ el => cityInput = el } />
</div>
<div>
<button>Go</button>
</div>
</form>
</div>
)
}
Demo
Hope it helps
I believe the error is because you're mixing regular function/class syntax with arrrow syntax.
Remember arrows function have no "this" or calling context so you'll need to make that changes at mentioned by Panther. All the best.
see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions for more details
actually I see you're using state in the component.
You'll have to convert it into a class or instead use a hook
const [formRes, setformRes] = React.UseState();
handleSubmit(event) {
event.preventDefault();
const data = new FormData(event.target);
setformRes(data)
console.log(formRes)
}
use class component.
Pass down the eventHandler function from Parent component.
functional component supposed to return some JSX. if you want do some mess staff, class component will be better!

Resources