unable to set this.state variable in node/react simple input example - javascript

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!

Related

Can't edit value of input element in React

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>
);
}
}

Get search value in state in ReactJS

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;

react state is not updated/passed to child component when child component is passed as a property

I am trying to create dynamic form, so I pass some jsx elements to a child component as a property. Even though the state is being updated, the updated state is not passed to the element. Below is the code:
This is the child component which maps over the passed controls and outputs them.
class Form extends Component {
render() {
return (
<div>
{this.props.controls.map((c, i) => {
return <React.Fragment key={i}>{c}</React.Fragment>;
})}
</div>
);
}
}
This is the App that calls the child component:
class App extends Component {
constructor(props) {
super(props);
this.state = {
username: '',
password: ''
};
this.controls = [
<input
type="text"
onChange={this.onChangeUsername}
value={this.state.username}
/>
];
}
componentDidUpdate() {
console.log(this.state);
}
render() {
return (
<div className="App">
<div className="app__group">
<h1>This is not working</h1>
<Form controls={this.controls} />
</div>
<div className="app__group">
<h1>This is working</h1>
<input
type="text"
onChange={this.onChangePassword}
value={this.state.password}
/>
</div>
</div>
);
}
onChangeUsername = e => {
console.log('onChangeUsername', e.target.value);
this.setState({ username: e.target.value });
};
onChangePassword = e => {
console.log('onChangePassword');
this.setState({ password: e.target.value });
};
}
As an example of the unexpected behaviour, when an input passed as a property to the child component, I cannot type in the input. The state gets updated but it's is not passed to the child, thus the text does not show.
On the other hand, a standard input element works, I can type and see the output.
What am I doing wrong?
the problem is that you are trying to make something "fixed" as something dynamic. lets go with a more functional approach and it will refresh each one of the inputs like if they are dynamic.
class App extends Component {
constructor(props) {
super(props);
this.state = {
username: '',
password: ''
};
}
componentDidUpdate() {
console.log(this.state);
}
render() {
return (
<div className="App">
<div className="app__group">
<h1>This is not working</h1>
<Form controls={this.controls()} />
</div>
</div>
);
}
controls = () => {
return [<input
type="text"
onChange={this.onChangeUsername}
value={this.state.username}
/>]
}
onChangeUsername = e => {
console.log('onChangeUsername', e.target.value);
this.setState({ username: e.target.value });
};
onChangePassword = e => {
console.log('onChangePassword');
this.setState({ password: e.target.value });
};
}

ReactJS: Why are the constructor called when setState changes the state

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!

enable button to submit only when all the fields are filled

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>
);
}

Categories

Resources