setState not a function after binding this - javascript

I have a simple form allowing users to create a plain text post. The code below generates a successful server side response following the createPostRequest call. However, following a successful post, I would like to update the state to empty out the postBody field and update the UI to reflect this change, and then allow users to make subsequent requests to post additional messages.
Currently, everything works well for the first request only, and after a successful initial request, the postBody field isn't emptying out and when attempting to change the value of the post field following the first initial request, every key stroke is resulting in the following error:
Uncaught TypeError: Cannot read property 'setState' of undefined
Note, what is a bit odd, is that I am getting the above error despite binding this to the onChange method in the constructor.
Did anyone run into this issue? I appreciate any suggestions on how to resolve.
constructor(props) {
super(props);
this.state = {
postBody : "",
location: "main"
};
this.onSubmit = this.onSubmit.bind(this);
this.onChange = this.onChange.bind(this);
}
onChange(e) {
this.setState({
[e.target.name] : e.target.value
});
}
onSubmit(e) {
e.preventDefault();
this.props.createPostRequest(this.state).then(
() => {
this.setState = ({
postBody : ""
});
}
)
}
render() {
return (
<div className="create-post-inner col-md-12">
<form id="createPost" onSubmit={ this.onSubmit } >
<textarea value={this.state.postBody} className="form-control postInput" name="postBody" onChange={ this.onChange } >
</textarea>
<span>The value of the state is {this.state.postBody}</span>
<input type="submit" className="submit btn btn-primary" />
</form>
</div>
);
}

there is an extra = after this.setState . Change the following to
this.props.createPostRequest(this.state).then(
() => {
this.setState({
postBody : ""
});
}
)

Related

State not being set by setState method

I am using React JS.
Here is my React class:
class SomeClass extends React.Component{
constructor(props){
super(props);
this.state = {
passAccount: {
email: "Email"
},
errorMessage: ''
};
}
submitRequest = (event) =>{
//this.state.passAccount.email === 'Email' ? this.setState({errorMessage:'Please enter a valid email'}) : axios.post(`http://localhost:5000/otp/generate-passcode/${this.state.passAccount.email.toString()}`, this.state.passAccount)
axios.post(`http://localhost:5000/generate/${String(this.state.passAccount.email)}`)
.then((response) => {
let result = response.data;
}).catch((error) =>{
this.setState({errorMessage: ''});
});
console.log(`submitRequest email: `, this.state.passAccount.email);
}
handleChange = (event) =>{
console.log(`input detected`);
let request = this.state.passAccount;
let requestValue = event.target.value;
this.setState({passAccount: requestValue});
}
render() {
return (
<Form onSubmit={this.handleSubmit}>
<Form.Group>
<Form.Label>Email Address</Form.Label>
<Form.Control type="text" value={this.state.email} onChange={this.handleChange} placeholder="Enter Email Address" style={{width: '25rem'}}/>
</Form.Group>
<Button type="submit" onClick={() => this.submitRequest()}>Get OTP</Button>
<Button type="submit">Sign In</Button>
</Form>
);
}
}
export default SomeClass;
In Chrome console, this is what I am getting:
input detected
submitRequest email: Email //here is what I want to fix
Form Submitted Successfully
My question is:
In the line where it says in the console:
submitRequest email: Email //here is what I want to fix, for some reason the setState method is not working what is the reason behind that ?
Is the error in the handleChange method or in the submitRequest method ? what is a possible fix ?
Thanks.
When you this.setState({passAccount: requestValue}); you are setting passAccount to current value edited in form. But passAccount is an object with email property.
So I would suggest to modify your code in this way:
handleChange = (event) =>{
console.log(`input detected`);
let request = Object.assign({}, this.state.passAccount); // copy this.state.passAccount into request
request.email = event.target.value; // change request email
this.setState({ passAccount: request }); // set passAccount
}
You have declared your state variable passAccount as an object which contains an email property. If you want to update this email property then in your handleChange function, you need to update the state like this:
this.setState({ passAccount: { email: requestValue });

ReactJs: Refreshing page after submit

I'm trying to use ReactJS, and I have encountered this problem:
I have a simple for with one field. And when I click on the submit button the page complete the code but immediately reload (i don't event have the time to read the console).
const INITIAL_STATE = {
teamName: '',
error: null,
};
class SearchingForm extends Component {
constructor(props){
super(props);
this.state = {
...INITIAL_STATE,
results: []
};
}
onSubmit = event => {
const { teamName } = this.state;
this.searching(this.state.teamName)
event.preventDefaul();
}
searching(teamName){
console.log("teamName: ", teamName)
}
onChange = event => {
this.setState({ [event.target.name]: event.target.value });
console.log(this.state)
};
render() {
const {
teamName,
error
} = this.state;
const isInvalid = teamName === '';
return (
<form onSubmit={this.onSubmit}>
<input
name="teamName"
value={teamName}
onChange={this.onChange}
type="text"
placeholder="Team Name"
/>
<button type="submit">Search</button>
</form>
);
}
}
Why do I have this behaviour?
Thank you.
There is a typo in your code
event.preventDefaul();
instead of
event.preventDefault();
and it should be the first line in the onSubmit function.
there is a typo instead of event.preventDefaul(); it should be
event.preventDefault().
and it used to be in the first line of your method.
Firstly you have to call event.preventDefault(); at first line of onsubmit function.
secondly their is typo error in preventDefault
Please use under given code:
onSubmit = event => {
event.preventDefaul();
const { teamName } = this.state;
this.searching(this.state.teamName);
}

State not being updated in React.js

I have created a basic form in react.js where I am able to get the values after the user submits the form.
However, when I try to change the values using the handleSubmit function, I don't see the changes made in the state.
I have made a copy of a state and changes are being reflected in the Copied State. But when I set the old state equal to the updated state, the changes are not reflected
My code is as follows
state = {
name: null,
ContactNumber: null
}
handleChange = (event) => {
this.setState({
[event.target.name] : event.target.value
})
}
handleSubmit = (event) => {
event.preventDefault()
let Copystate = JSON.parse(JSON.stringify(this.state))
Copystate.ContactNumber = 100
console.log(Copystate) // displaying the contact number as 100
this.setState({
state : Copystate
})
console.log(this.state) // displays the number which was submitted in the form
}
render(){
return(
<div>
<h2>Form</h2>
<form onSubmit={this.handleSubmit}>
<div>
<label>Name</label>
<input type="text" name="name" required = {true} onChange = {this.handleChange}/>
<label>Contact Number</label>
<input type="number" name="ContactNumber" required = {true} onChange = {this.handleChange}/>
<button type="submit" label="submit" >Submit</button>
</div>
</form>
</div>
);
}
}
Can anyone please let me know where I am going wrong? Thanks
Notice: setState is asynchronous: document state-updates-may-be-asynchronous
You can use a callback function to get the updated state
this.setState({state: Copystate}, () => {console.log(this.state)});
Or you can choose to use async/await
handleSubmit = async (event) => {
await this.setState({state: Copystate});
console.log(this.state);
}
Those two methods won't affect re-render since once the state is been updated, the re-render would proceed.
If you console in the render() you would find that it should always be updated finally.
render() {
console.log(this.state);
return (
...
)
}
setState is asynchronous.
So, you can do one of the following -
1. make a callback in setState to log the state or
2. write your console statement in the render function.
Why do you do this?
let Copystate = JSON.parse(JSON.stringify(this.state))
Copystate.ContactNumber = 100
You can change the handleSubmit to be like the following:
handleSubmit = (event) => {
event.preventDefault();
let { ContactNumber } = this.state;
ContactNumber = 100;
console.log(ContactNumber); // displaying the contact number as 100
this.setState({
ContactNumber: ContactNumber
}, () => {
console.log(this.state) // displays the number which was submitted in the form
})
}

ReactJS : Form Data Capture : values not setting properly

I am trying out with a small react app, with a form based data capture, after keying in the values, when user clicks submit button, values need to be captured in state variable. But, state variable contains null value in handleSubmit function. For clarity, code snippets are given below,
Constructor code, for the sake of completeness/clarity,
constructor(props)
{
super(props);
this.state = {
username : '',
};
}
handleChange function is where I set state variable,
handleChange = (event) => {
this.setState( [event.target.username]: event.target.value );
}
handleSubmit function is where, I print state variable, which contains null value, instead of user inputted value.
handleSubmit = () => {
console.log(this.state.username);
}
Component's render function is given below, which invokes handleChange
and handleSubmit.
render() {
return(
<div>
<form>
<label>
Title:
<input
type = "text"
name="username"
onChange={event => this.handleChange(event)}/>
</label>
<button
label="Submit"
onClick={this.handleSubmit}>
Submit
</button>
</form>
</div>
)};
I am missing on something. I am new to react. Kindly advise.
you need setState's argument to be an object.
handleChange = (event) => {
this.setState({ [event.target.username]: event.target.value });
}

React Controlled Input Unable to Type [onChange]

Sorry if this sounds like a repeated question,I have checked the existing answer and none of them seemed to solve my problem.
I'm initially setting a value of a controlled input like so value ={this.props.someValue} (which comes from an API)
Later,I'm trying to let the user type the value on the form,
class ProfilePage extends Component {
constructor(props) {
super(props);
this.state = {
name: "",
lastname: "",
errors : ""
};
this.handleOnchange = this.handleOnchange.bind(this);
}
handleInputChange = event => {
const { target } = event;
this.setState({
[target.name]: target.value,
errors: errors
});
};
handleOnchange(event) {
const { target } = event;
this.setState({
[target.name]: target.value
});
}
render(){
let firstName = [];
let lastName = [];
if (this.props.profile) {
firstName = this.props.profile.first_name;
lastName = this.props.profile.last_name;
}
return (
<div class="container">
<label for="first-name">First Name</label>
<input
type="text"
placeholder="First Name"
name="name"
value={firstName.value}
onBlur={this.handleInputChange}
onChange={this.handleOnchange.bind(this)}
className={
errors && errors.name
? "inputError"
: "inputValid"
}
/>
</div>
)
}
}
My onChange event fires successfully however,it doesn't let me type anything in the input box.What Am I missing ?
You value logic is wrong. Whenever this.state.name changes you still keep sending this.props.profile.first_name as value.
onChange updates state and on re-render you need to check whether it has value or not.
My suggestion is to stick with state value and "ignore" this.props.profile on render method.
One possible solution is hand it over in the constructor:
constructor(props) {
super(props)
this.state = {
...
name: this.props.profile ? this.props.profile.first_name.value : ''
}
}
Your form is re-rendered every time your handleOnchange function runs, due to the this.setState({...}) call in it. That is correct so far, but you have to update the input value manually. At the moment, your input field re-takes the value firstname.value at every re-render, which is something static out of this.props, that's why the value will never change.
You only have to set the input value to the state variable you are updating in your handleOnchange function, for instance this.state.name. Furthermore, you have to initialise the state variable in the constructur with the value you want to display at load time (not with an empty string like now). In your example, that would mean:
constructor(props) {
super(props);
this.state = {
name: props.profile.first_name.value,
lastname: "",
errors : ""
};
this.handleOnchange = this.handleOnchange.bind(this);
}
Additionally you are doing the this binding of your handleOnchange function twice, once in the constructor and once in the input field assignment. It would be sufficient to do it only in the constructor, since it is the preferred way of doing that. With that in mind, you can just assign the function in your input field like: onChange={this.handleOnchange}

Categories