I am new in ReactJS and trying to get the search input box value and store it in a state.
My code:
<form className="search-form" onSubmit={this.handleSubmit}>
<input type="search" name="search" ref={(input) => this.query = input}
placeholder="Search..." />
<button className="search-button" type="submit" id="submit">Go!</button>
</form>
Inside constructor:
this.handleSubmit = this.handleSubmit.bind(this);
And
handleSubmit = e => {
e.preventDefault();
this.setState({search: this.query.value});
console.log(this.state.search) //Returns undefined
e.currentTarget.reset();
}
Any help is highly appreciated.
I would suggest you to use controlled input approach.
state = {
value: null,
}
handleValue = (e) => this.setState({ value: e.target.value });
Then you don't have to use ref.
<input
type="search"
name="search"
onChange={this.handleValue}
placeholder="Search..."
/>
This code may help you:
import React from 'react';
class search extends React.Component{
constructor(props)
{
super(props);
this.state = {value: ''};
this.addValue = this.addValue.bind(this);
this.updateInput = this.updateInput.bind(this);
}
addValue(evt)
{
evt.preventDefault();
if(this.state.value !==undefined)
{
alert('Your input value is: ' + this.state.value)
}
}
updateInput(evt){
this.setState({value: evt.target.value});
}
render()
{
return (
<form onSubmit={this.addValue}>
<input type="text" onChange={this.updateInput} /><br/><br/>
<input type="submit" value="Submit"/>
</form>
)
}
}
export default search;
Related
I have a problem with my React project, I have an input element like below but I can't edit the text of the input. I just can edit the input text only when I delete the value attribute, but I want a default value for it.
<div className="form-group">
<label>Email:</label>
<input
className="form-input"
type="text"
value="l.h.thuong181#gmail.com"
name="email">
</input>
</div>
If you've an uncontrolled component, you might want to use the defaultValue property instead of value (See this reference)
You can use useRef or defaultValue
import React, { useRef, useEffect } from "react";
const input = useRef();
useEffect(() => {
input.current.value = "l.h.thuong181#gmail.com";
}, []);
<input ref={input} className="form-input" type="text" name="email" />`
Here is a sample code how to use inputs in react
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
Set the default value inside the state object and attach a change handler to the input to capture the changes:
Sample codesandbox: https://codesandbox.io/s/react-basic-class-component-22fl7
class Demo extends React.Component {
constructor(props) {
super(props);
this.state = {
inputValue: 'l.h.thuong181#gmail.com'
};
}
handleChange = event => {
this.setState({ inputValue: event.target.value }, () =>
console.log(this.state.inputValue)
);
};
render() {
return (
<div className="form-group">
<label>Email:</label>
<input
className="form-input"
type="text"
value={this.state.inputValue}
onChange={this.handleChange}
name="email">
</input>
</div>
);
}
}
export default class extends Component {
constructor(props) {
super(props)
this.state = { searchTerm: ''}
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleChange = (event) => {
this.setState({ searchTerm: event.target.value })
console.log('event.target.value')
console.log(event.target.value)
console.log('this.searchTerm')
console.log(this.searchTerm)
}
handleSubmit = () => {
console.log('Button Clicked')
console.log(this.searchTerm)
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Search:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
)
}
}
My issue is that the console is showing undefined for this.seachTerm value and the event.target.value is showing the correct output. Why is the state variable not being set? I have changed this answer using the same example from an answer below.
https://reactjs.org/docs/forms.html#controlled-components
Is the class not setup correctly? This is a sub-component.
Use this.state.searchTerm instead of this.searchTerm and you will be fine!
I'm a newbie to ReactJS and I have made an app where you can submit a name and email. The name and mail should be displayed in a list at the bottom of the page. It is displayed for a short period, but then the constructor gets called and clears the state and the list.
Why is the constructor called after the state change? I thought the constructor only runs once and then the render-method runs after setState() changes the state.
class App extends React.Component {
constructor(props) {
super(props);
console.log("App constructor");
this.state = {
signedUpPeople: []
};
this.signUp = this.signUp.bind(this);
}
signUp(person) {
this.setState({
signedUpPeople: this.state.signedUpPeople.concat(person)
});
}
render() {
return (
<div>
<SignUpForm signUp={this.signUp} />
<SignedUpList list={this.state.signedUpPeople} />
</div>
);
}
}
class SignUpForm extends React.Component {
constructor(props) {
super(props);
console.log("SignUpForm constructor");
this.state = {
name: "",
email: ""
};
this.changeValue = this.changeValue.bind(this);
this.onSubmitForm = this.onSubmitForm.bind(this);
}
changeValue(event) {
const value = event.target.value;
const name = event.target.name;
this.setState({
name: value
});
}
onSubmitForm() {
this.props.signUp(this.state);
this.setState({
name: "",
email: ""
});
}
render() {
console.log("SignUpForm render");
return (
<div>
<h2>Sign up</h2>
<form onSubmit={this.onSubmitForm}>
<label htmlFor="name">Name:</label>
<input id="name" name="name" onChange={this.changeValue} />
<br />
<label htmlFor="email">E-mail:</label>
<input id="email" name="name" onChange={this.changeValue} />
<input type="submit" value="Sign up" />
</form>
</div>
);
}
}
class SignedUpList extends React.Component {
render() {
console.log("SignedUpList render");
return (
<div>
<h2>Already signed up</h2>
<ul>
{this.props.list.map(({ name, email }, index) => (
<li key={index}>
{name}, {email}
</li>
))}
</ul>
</div>
);
}
}
ReactDOM.render(<App />, window.document.getElementById("app"));
See CodePen example
The default behavior of a form with input of type submit is to post back to the server.
<input> elements of type "submit" are rendered as buttons. When the
click event occurs (typically because the user clicked the button),
the user agent attempts to submit the form to the server.
You can pass the event object of the submit handler and use the event.preventDefault method to prevent the form from posting back:
onSubmitForm(e) {
e.preventDefault();
this.props.signUp(this.state);
this.setState({
name: "",
email: ""
});
}
Here is a running snippet of your code:
class App extends React.Component {
constructor(props) {
super(props);
console.log("App constructor");
this.state = {
signedUpPeople: []
};
this.signUp = this.signUp.bind(this);
}
signUp(person) {
this.setState({
signedUpPeople: this.state.signedUpPeople.concat(person)
});
}
render() {
return (
<div>
<SignUpForm signUp={this.signUp} />
<SignedUpList list={this.state.signedUpPeople} />
</div>
);
}
}
class SignUpForm extends React.Component {
constructor(props) {
super(props);
console.log("SignUpForm constructor");
this.state = {
name: "",
email: ""
};
this.changeValue = this.changeValue.bind(this);
this.onSubmitForm = this.onSubmitForm.bind(this);
}
changeValue(event) {
const value = event.target.value;
const name = event.target.name;
this.setState({
name: value
});
}
onSubmitForm(e) {
e.preventDefault();
this.props.signUp(this.state);
this.setState({
name: "",
email: ""
});
}
render() {
//console.log('SignUpForm render');
return (
<div>
<h2>Sign up</h2>
<form onSubmit={this.onSubmitForm}>
<label htmlFor="name">Name:</label>
<input id="name" name="name" onChange={this.changeValue} />
<br />
<label htmlFor="email">E-mail:</label>
<input id="email" name="name" onChange={this.changeValue} />
<input type="submit" value="Sign up" />
</form>
</div>
);
}
}
class SignedUpList extends React.Component {
render() {
//console.log('SignedUpList render');
return (
<div>
<h2>Already signed up</h2>
<ul>
{this.props.list.map(({ name, email }, index) => (
<li key={index}>
{name}, {email}
</li>
))}
</ul>
</div>
);
}
}
ReactDOM.render(<App />, window.document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app">
</div>
onSubmitForm(e) {
e.preventDefault(); // prevent the form from refreshing the page
this.props.signUp(this.state);
this.setState({
name: "",
email: ""
});
}
It is working with your codepen link :)
Have a deep look at this :
React - Preventing Form Submission
or
https://medium.com/#ericclemmons/react-event-preventdefault-78c28c950e46
Thank you all for your help! :-)
e.preventDefault();
Did fix the problem. Thanks!
I have a form which has 3 field. First two fields are email_from and email_subject and the last field is an editor. I have used draftjs for editor. If there is no editor i could enable and disable the submit button but due to the inclusion of the editor i did not know how can i enable the button only when all the fields are filled with no error.
Here is my code.
AdminEditor is the component which has draftjs editor
class EmailTemplate extends React.Component {
state = {
emailSubject: '',
emailFrom: ''
};
handleChange = event =>
this.setState({ [event.target.name]: event.target.value });
handleSubmit = event => {
event.preventDefault();
};
render() {
const { emailSubject, emailFrom } = this.state;
return (
<form onSubmit={this.handleSubmit}>
<FieldGroup
id="formControlsText"
name="emailSubject"
type="text"
label="Email Subject"
placeholder="Enter Email Form"
onChange={this.handleChange}
validationState={emailSubject ? 'success' : 'error'}
required
/>
<FieldGroup
id="formControlsText"
name="emailFrom"
type="email"
label="Email From"
placeholder="Enter Email From"
onChange={this.handleChange}
validationState={emailFrom ? 'success' : 'error'}
required
/>
<AdminEditor />
<Button type="submit">
Submit
</Button>
</form>
);
}
}
export default EmailTemplate;
class AdminEditor extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
editorState: EditorState.createEmpty(),
isEmpty: true
};
}
onEditorStateChange = editorState => {
this.setState({
editorState
});
};
onEditorChange = editorContent => {
this.setState({
editorContent
});
};
handleChange = event =>
this.state.editorState.getCurrentContent().hasText()
? this.setState({ isEmpty: false })
: this.setState({ isEmpty: true });
render() {
const { editorState } = this.state;
return (
<div>
<Editor
editorState={this.state.editorState}
initialContentState={rawContentState}
toolbarClassName="home-toolbar"
wrapperClassName="home-wrapper"
editorClassName="home-editor"
onEditorStateChange={this.onEditorStateChange}
toolbar={{
textAlign: { inDropdown: true },
}}
onContentStateChange={this.onEditorChange}
placeholder="write text here..."
onChange={this.handleChange}
/>
</div>
);
}
}
export default AdminEditor;
Can anyone please help me?
There are many ways to do this, mostly based around passing some callbacks down into the controlled component which updates the state in the parent.
A simple way would be to pass a handler that sets a flag if the editor is empty or not:
class AdminEditor extends React.PureComponent {
...
handleChange = event =>
this.props.setEditorIsEmpty(
this.state.editorState.getCurrentContent().hasText()
);
Then in EmailTemplate:
setEditorIsEmpty(editorIsEmpty) {
this.setState({
editorIsEmpty
});
}
render() {
const { emailSubject, emailFrom } = this.state;
return (
<form onSubmit={this.handleSubmit}>
...
<AdminEditor
setEditorIsEmpty={this.setEditorIsEmpty}
/>
<Button
type="submit"
disabled={!emailSubject || !emailFrom || editorIsEmpty}>
Submit
</Button>
</form>
);
}
I'm trying to make reusable Form and Input components and so far got to following:
Form
import React from 'react'
import classNames from 'classnames/bind'
import styles from './style.scss'
const cx = classNames.bind(styles)
export default class Form extends React.Component {
constructor (props) {
super(props)
this.submitForm = this.submitForm.bind(this)
}
submitForm (e) {
e.preventDefault()
this.props.onSubmit()
}
render () {
return (
<form className={cx('Form')} onSubmit={this.submitForm}>
{this.props.children}
</form>
)
}
}
Form.propTypes = {
children: React.PropTypes.any.isRequired,
onSubmit: React.PropTypes.func.isRequired
}
Input
import React from 'react'
import classNames from 'classnames/bind'
import styles from './style.scss'
const cx = classNames.bind(styles)
export default class Input extends React.Component {
constructor (props) {
super(props)
this.state = {
value: this.props.value || ''
}
this.changeValue = this.changeValue.bind(this)
}
changeValue (e) {
this.setState({value: e.target.value})
}
render () {
return (
<div className={cx('Input')}>
<input
type={this.props.type}
value={this.state.value}
required={this.props.required}
onChange={this.changeValue}
placeholder={this.props.placeholder || ''}
noValidate />
</div>
)
}
}
Input.propTypes = {
type: React.PropTypes.string.isRequired,
value: React.PropTypes.string,
required: React.PropTypes.bool,
placeholder: React.PropTypes.string
}
I then use them within some another component, lets say HomePageComponent
<Form onSubmit={this.loginUser}>
<Input type='email' placeholder='email' />
<Input type='password' placeholder='password' />
<Input type='submit' value='Submit' />
</Form>
This all works well, but how would I get input values and use them to set state of HomePageComponent to this.state= { email: [value from input email], password: [value from password input] }
You don't need to store the value in the Input component.
You can get the input values by keeping references to individual inputs:
<Form onSubmit={this.loginUser}>
<Input ref='email' type='email' placeholder='email' />
<Input ref='password' type='password' placeholder='password' />
<Input type='submit' value='Submit' />
</Form>
Then, in loginUser you can access these using:
const email = ReactDOM.findDOMNode(this.refs.email).value;
const password = ReactDOM.findDOMNode(this.refs.password).value;
if you add the name attribute to your input elements, you can access their values this way. Hope this helps
import React, { PropTypes, Component } from 'react';
class Form extends Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e) {
e.preventDefault();
const form = e.target.elements;
console.log(form.email.value);
console.log(form.password.value);
}
render() {
return (
<form className={cx('Form')} onSubmit={this.handleSubmit}>
<Input type='email' placeholder='email' name='email' />
<Input type='password' placeholder='password' name='password' />
<button type="submit">Submit</button>
</form>
);
}
}