How to add event handlers within const in React? - reactjs

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!

Related

ref value undefined 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

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)

reactjs container component form values

I am new to react and am trying to get the value from the firstName input in handleSubmit. handleSubmit is working but for some reason the input value is undefined. I tried following some other examples but they were all forms in React components.
let SomeForm = (props) => {
let firstName = '';
const handleSubmit = (e) => {
e.preventDefault();
console.log(firstName);
}
return (
<div>
<form onSubmit={handleSubmit}>
<TextField
floatingLabelText="First Name"
floatingLabelFixed={true}
underlineStyle={styles.underlineStyle}
underlineFocusStyle={styles.underlineFocusStyle}
value={firstName}
/>
<input type="submit" value="Submit" />
</form>
</div>
)
}
SomeForm = connect()(SomeForm)
export default SomeForm
You need to add onChange to the TextField to handle the updates. And because SomeForm is a stateful component, you may need to use a class component instead of a stateless functional component.
class SomeForm extends React.Component {
state = {
firstName: ''
};
handleChange = (e, value) => {
this.setState({ firstName: value });
};
handleSubmit = (e) => {
e.preventDefault();
console.log(this.state.firstName);
};
render () {
return (
<div>
<form onSubmit={this.handleSubmit}>
<TextField
id="text-field-controlled"
floatingLabelText="First Name"
floatingLabelFixed={true}
underlineStyle={styles.underlineStyle}
underlineFocusStyle={styles.underlineFocusStyle}
value={this.state.firstName}
onChange={this.handleChange}
/>
<input type="submit" value="Submit" />
</form>
</div>
)
}
}
See the API and examples of TextField here: http://www.material-ui.com/#/components/text-field
You need function that you will throw in your TextField component and with onChange you can get value of input.
handleChange(e){
Console.log(e.target.value)
}
And in TextField
<TextField onChange={this.handleCahnge}/}
Or use refs
<TextField ref="textfield" />
And get value with this.refs.textfield.getValue()

Submitting redux form values

I am new to react and redux technology. now started building an application that contains several redux forms. We want to submit simple form with values.
For ex: login form
Username : text input field
Password: text input field
Submit button
After entering values in fields and click on submit button i want to get the username and password field values in object or json data .. so that I can store it to my server with POST method.
Right now we are using handleSubmit(), but data is not coming as object
1 - The best practice to deal with input values are making them controlled. Which means :
Instead of
<input type='password' />
You do :
<input
type='password'
value={password}
onChange={ event => myInputHandler( event.target.value ) }
/>
The value might come from your state, redux state or as a props etc.
Your handler function differs according to where you store it.
I will give you an example with react state :
<input
type='password'
value={this.state.password}
onChange={ event => this.setState({ password : event.target.value }) }
/>
So whenever someone types, your onChange handler will be called, so that your react state will update with the input ( event.target.value ).
2 - If you need these values when a user submits, then you need to wrap these input fields within a form element and attach a onSubmit handler.
onSubmitHandler( event ){
event.preventDefault()
let password = this.state.password
// use password or other input fields, send to server etc.
}
<form onSubmit={ event => this.onSubmitHandler(event) }>
<input
type='password'
value={this.state.password}
onChange={ event => this.setState({ password : event.target.value }) }
/>
</form>
Hope you get what you need.
If you are using redux to store state then use redux-from then use redux from
import React from 'react'
import {Field, reduxForm} from 'redux-form'
const SimpleForm = props => {
const {handleSubmit, submitting} = props return (
<form onSubmit={handleSubmit(e=>console.log('your form detail here', e))}>
<div>
<label>First Name</label>
<div>
<Field name="firstName" component="input" type="text" placeholder="First Name" />
</div>
</div>
<div>
<label>Last Name</label>
<div>
<Field name="lastName" component="input" type="text" placeholder="Last Name" />
</div>
</div>
<div>
<button type="submit" disabled={pristine || submitting}>Submit</button>
</div>
</form>
) }
export default reduxForm({ form: 'simple'})(SimpleForm)
Go here for more detail
https://redux-form.com
I put the name of the input as the key that I want to use.
Then each time the input changes I destructure the event passed to the onChange function, and I use the name,value to update the state.
On form submit make sure to use preventDefault(); in order to avoid the page refreshing.
import React, { Component } from 'react'
class FormExample extends Component {
constructor(props){
super(props)
this.state = {
formData: {}
}
}
handleInputChange = ({ target: { name,value } }) => {
this.setState({
formData: {
...this.state.formData,
[name]: value
}
})
}
handleFormSubmit = e => {
e.preventDefault()
// This is your object
console.log(this.state.formData)
}
render() {
return(
<div>
<Form
handleSubmit={this.handleFormSubmit}
handleChange={this.handleInputChange}
/>
</div>
)
}
}
const Form = ({ handleSubmit, handleChange }) => (
<form onSubmit={handleSubmit}>
<input onChange={handleChange} name="username" type="text" placeholder="Username" />
<input onChange={handleChange} name="password" type="password" placeholder="Password" />
<button>Submit</button>
</form>
)
export default FormExample

How to get an input value using "refs" in react-bootstrap form?

I'm trying to create a form that appears in modal. So when user input a value, that value is stored in local storage. Here's a picture that help's you to understand what I mean:
Here is the code of the form:
function FieldGroup({id, label, help, ...props}) {
return (
<ReactBootstrap.FormGroup controlId={id}>
<ReactBootstrap.ControlLabel>{label}</ReactBootstrap.ControlLabel>
<ReactBootstrap.FormControl {...props} />
{help && <ReactBootstrap.HelpBlock>{help}</ReactBootstrap.HelpBlock>}
</ReactBootstrap.FormGroup>
);
}
const formInstance = (
<form>
<FieldGroup
id="formControlsText"
type="text"
label="Text"
placeholder="Recipe Name"
inputRef={ref => { this.input = ref; }}
/>
<ReactBootstrap.FormGroup controlId="formControlsTextarea">
<ReactBootstrap.ControlLabel>Ingredients</ReactBootstrap.ControlLabel>
<ReactBootstrap.FormControl componentClass="textarea" placeholder="Enter Ingredients" />
</ReactBootstrap.FormGroup>
</form>
);
As I've read in bootstrap React tutorial, I should add
<FormControl inputRef={ref => { this.input = ref; }} /> to the FormControl props. But after adding it I get an error when modal form is invoked:
`
I just made this issue. My code:
<FormControl
componentClass="input"
placeholder="Enter recipe title"
inputRef={(ref) => {this.input = ref}}
defaultValue={title}/>
</FormGroup>
And then you can get the value from <FormControl> in some handler like this:
console.log(this.input.value);
Details can be found in my repo: https://github.com/kerf007/recipebook
I have same problem with you, and this is my solution
const FieldGroup = ({id, label, help, inputRef, ...props}) =>
<FormGroup controlId={id}>
<ControlLabel>{label}</ControlLabel>
<FormControl {...props} inputRef={inputRef}/>
{help && <HelpBlock>{help}</HelpBlock>}
</FormGroup>
and my form
<form>
<FieldGroup
id="bookName"
type="text"
label="Name"
placeholder="Enter name..."
inputRef = {(input) => this.inputName = input }
/>
<FieldGroup
id="bookAuthor"
label="Author"
type="text"
placeholder="author 's name..."
inputRef={(input) => this.inputAuthor = input}
/>
</form>
then you can get book 's name and author 's name value by:
this.inputName.value and this.inputAuthor.value
This issue (or more like a change in the way it works) is related to React-Bootstrap. The way you're doing it won't work anymore.
The <FormControl> component directly renders the or other specified component. If you need to access the value of an uncontrolled <FormControl>, attach a ref to it as you would with an uncontrolled input, then call ReactDOM.findDOMNode(ref) to get the DOM node. You can then interact with that node as you would with any other uncontrolled input.
Here's an example:
var React = require('react');
var ReactDOM = require('react-dom');
var FormControl = require('react-bootstrap').FormControl;
React.createClass({
render: function() {
return (<FormControl ref="formControl" />);
},
getFormControlNode: function() {
// Get the underlying <input> DOM element
return ReactDOM.findDOMNode(this.refs.formControl);
}
});
As soon as you get the DOM element, you will be able to retrieve the value: this.getFormControlNode().value or do anything else that you want.
PS: Here's a related github issue on this topic.
This worked for me, using https://reactjs.org/docs/refs-and-the-dom.html
constructor(props) {
super(props);
this.email = React.createRef();
}
submit() {
var email = this.email.current.value;
console.log(email);
}
render() {
return (
<Form>
<Form.Control type="email" placeholder="Your email" ref={this.email} />
<Button variant="primary" onClick={()=>this.submit()}>Send</Button>
</Form>
);
}
I think what it suggests to use is the ref callback attribute, so just change inputRef to ref.
FYI: https://facebook.github.io/react/docs/refs-and-the-dom.html
Hello this solution worked for me!
<Form
noValidate
validated={validated}
onSubmit={(e) => this.handleSubmit(e)}
style={{ width: '100%' }}
>
<Form.Group controlId="formBasicEmail">
<Form.Label>Email address</Form.Label>
<Form.Control type="email" placeholder="Enter email" inputRef={(ref) => { this.email = ref }} required />
<Form.Text className="text-muted"> Well never share your email with anyone else.
</Form.Text>
</Form.Group>
</Form>
handleSubmit(event) {
console.log(event.target.elements.formBasicPassword.value)
}
I think I found how to get the ref from React-Bootstrap <Form/>.
import React, {createRef} from 'react'
interface definedProps {}
interface definedState {
myRef: Object //I didn't found the more accurate type
}
export default class SomeClass extends React.Component<definedProps,definedState> {
state = {
myRef: React.createRef<Form<any>>() //That's it!
}
const handleClose = () => {
console.log('this.state.myRef: ', this.state.myRef); //Here we can take data from Form
debugger; //todo: remove
}
render() {
return (
<div>
<Form ref={this.state.myRef}> { /*Here we're connecting the form's ref to State*/}
<Form.Group controlId='formName'>
<Form.Control
type='text'
placeholder='Enter Name'
/>
</Form.Group>
...
<Button
variant='primary'
onClick={handleClose}
>
Save Changes
</Button>
</Form>
</div>
)
}
}

Resources