props not being passed properly - reactjs - reactjs

I have two components, one of which is used for filling out a form, the other is for displaying the input once it is submitted. However, it currently only displays the input until the form is submitted, and then it goes away. What is happening to the state of the parent component when the form is submitted?
class Form extends Component {
constructor(props) {
super(props);
this.state = {
equation: null
};
}
render() {
return (
<div>
<form onSubmit={this.mySubmitHandler}>
<input
type="text"
name="equation"
onChange={this.handleInputChange}
/>
</form>
<Parser value={this.state.equation}/>
</div>
);
}
handleInputChange = event => {
event.preventDefault();
this.setState({
[event.target.name]: event.target.value
});
};
mySubmitHandler = event => {
event.preventDefault();
this.setState({ equation: event.target.value });
alert("You are submitting " + this.state.equation);
console.log(this.state.equation);
};
}
class Parser extends Component {
render() {
return <div>{this.props.value}</div>;
}

The problem here is the event.target.value from the form submit event.
Since the event is coming from form submit, the target element is form and there is no value in the target element.
Update the component like below will solve your problem.
import React, {Component } from 'react';
export default class Hello extends Component {
constructor(props) {
super(props);
this.state = {
equation: null
};
}
render() {
return (
<div>
<form onSubmit={this.mySubmitHandler}>
<input
type="text"
name="equation"
onChange={this.handleInputChange}
/>
<button type="submit">Submit</button>
</form>
<Parser value={this.state.equation}/>
</div>
);
}
handleInputChange = event => {
event.preventDefault();
this.setState({
[event.target.name]: event.target.value
});
};
mySubmitHandler = event => {
event.preventDefault();
alert("You are submitting " + this.state.equation);
console.log(this.state.equation);
};
}
class Parser extends Component {
render() {
return <div>{this.props.value}</div>;
}
}
Check the stackblitz solution.Stackblitz

In mySubmitHandler, event.target.value is undefined, which is why the Parser text is disappearing. If you need to use equation in the submit handler, just use this.state.equation because it is has already been set via handleInputChange
mySubmitHandler = event => {
event.preventDefault();
// event.target.value is undefined
// this.state.equation has already been set via this.handleInputChange
this.setState({ equation: event.target.value });
alert("You are submitting " + this.state.equation);
console.log(this.state.equation);
};

You should not be using this.setState({equation: event.target.value}); in mySubmitHandler.
The event.target for submit is the form itself and it has no value.
Therefore it sets equation to undefined.
The reason you see the correct state when you console.log() it is because setState is async and the state in that function call still has the old value with it.
Remove it and see if it works.

You need to maintain two states equation and inputequation.
Now when you change input setstate inputequation. When you submit setstate equation to inputequation.
And one more thing
<input value={this.state.inputequation}/>
input should be controlled via your state.

Here, I modified the handleInputChange and mySubmitHandler you use this
handleInputChange = event => {
event.preventDefault();
this.setState({
equation: event.target.value
});
};
mySubmitHandler = event => {
event.preventDefault();
alert("You are submitting " + this.state.equation);
console.log(this.state.equation);
};

You should check this stackblitz solution
I have used your code.
import React, { Component } from 'react';
class Form extends Component {
constructor(props) {
super(props);
this.state = {
equation: null
};
}
render() {
return (
<div>
<form onSubmit={this.mySubmitHandler}>
<input
type="text"
name="equation"
onChange={this.handleInputChange}
/>
</form>
<Parser value={this.state.equation}/>
</div>
);
}
handleInputChange = event => {
this.setState({
[event.target.name]: event.target.value
});
};
mySubmitHandler = event => {
event.preventDefault();
alert("You are submitting " + this.state.equation);
};
}
class Parser extends Component {
render() {
return <div>{this.props.value}</div>;
}
}

Simple fix. You are accessing the incorrect property of the form.
this.setState({ equation: event.target.value });
This needs to be the name of the form element which is equation:
this.setState({ equation: event.target.equation.value });
Your updated handler:
mySubmitHandler = event => {
event.preventDefault();
this.setState({ equation: event.target.equation.value });
};
JSFiddle

Related

calling function in React SetState gives error that userName is unlabelled why?

import React,{Component} from 'react'
class Formhandler extends Component {
constructor(props) {
super(props)
this.state = {
userName:""
}
}
changer=(event)=>{
this.setState(()=>{
userName : event.target.value
})
}
render()
{
return(
<div>
<label>UserName</label>
<input type="text" value={this.state.userName} onChange={this.changer}/>
</div>
)
}
}
export default Formhandler
You are getting the error because of invalid syntax.
Update changer function
changer = (event) => {
this.setState({ userName: event.target.value });
};
You need to return an object inside the setState function but you are not that's the source of issue(syntax error).
use a function inside setState when your new state value would depend on your previous state value, where the function passed inside the setState will receive previous state as argument
changer = (e) => {
this.setState((prevState) => ({
userName : e.target.value
})
);
}
pass an object to update the state, use this when it doesn't depend on your previous state value.
changer = (e) => {
this.setState({ userName: e.target.value });
};
import React from "react";
class Formhandler extends React.Component {
constructor(props) {
super(props);
this.state = {
userName: "",
};
}
changer(event) {
this.setState(() => ({
userName: event.target.value,
}));
}
render() {
return (
<div>
<label>UserName</label>
<input
type="text"
value={this.state.userName}
onChange={this.changer.bind(this)}
/>
</div>
);
}
}
export default Formhandler;
It will work, compare your version and this

React : How can I edit the form?

I am using localStorage to store the form details. When the component is mounted I am getting the data in the console. How can I show the data in the form and edit it? I've set the edited state but I am not getting how can I achieve this so that the values will be prefilled?
Here's the code :
class MileStoneForm extends Component {
constructor(props){
super(props)
this.state={
deliverable_name:"",
due_date:"",
deliverable_notes:"",
milestone_based_payment:false,
deliverable_name_error:"",
due_date_error:"",
deliverable_notes_error:"",
percent_rate:0,
percent_rate_error:"",
due_date_select:false,
edit:false,
milestonedata:null;
}
}
componentDidMount(){
let milestonedata=JSON.parse(localStorage.getItem('mileStoneData'))
console.log(milestonedata)
if(this.state.edit===true){
this.setState({
milestonedata:milestonedata
},()=>{this.setEditMileStoneData()})
}
}
setEditMileStoneData=()=>{
const {milestonedata}=this.state
let data={
deliverable_name:milestonedata.milestoneName,
deliverable_notes:milestonedata.description,
due_date:milestonedata.dueDate,
milestone_based_payment:milestonedata.isMilestoneBasedPayment,
percent_rate:milestonedata.percentageRate
}
this.setState({...data})
}
handleSubmit=()=>{
const {deliverable_name,deliverable_name_error,deliverable_notes,deliverable_notes_error,
due_date,due_date_error,milestone_based_payment,percent_rate}=this.state
let pass=true
if(pass){
let data={
description: deliverable_notes,
dueDate: due_date,
isDeleted: false,
isMilestoneBasedPayment: milestone_based_payment,
milestoneName: deliverable_name,
percentageRate: percent_rate,
}
console.log(data)
this.props.handleData(data)
localStorage.setItem('mileStoneData',JSON.stringify(data))
this.setState({
deliverable_name:'',
deliverable_name_error:'',
deliverable_notes:'',
deliverable_notes_error:'',
milestone_based_payment:false,
percent_rate:'',
due_date:'',
due_date_error:''
})
}
}
export default MileStoneForm
You should take a look at the "controlled components" section from React docs.
The thought behind it is:
You create a state object for your form.
You add the state for each form field as its value
You add a function to onChange that updates the satate.
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>
);
}
}
Controlled component is the way to go here. I usually like to do it this way.
handleChange = (e) => {
// This way when we a change is made within the field this function is called and the name from the input will be changed with the new value provided
this.setState({ [e.target.name] : e.target.value })
}
render(){
<TextInput value = { this.state.NAME_THIS_CORRELATING_TO_THE_KEY_IN_STATE } name = "NAME_THIS_CORRELATING_TO_THE_KEY_IN_STATE" onChange = { this.handleChange }
}
We then do this for all of our components

React: how do I use onSubmit to change state?

I'm quite new to React, and have only completed a few projects with it. I'm currently trying to create a form that, using onSubmit, changes the state of "isSubmitted" from false to true. When "isSubmitted" is true, I'd like to render another component to show the results of the selection.
What's currently happening is that onChange is working and I can see the value of "selectedI" set as state in the console.log when I change it. However, when I click submit, this state of "isSubmitted" doesn't change.
My code is below. Any help is greatly appreciated!
import React, { Component } from "react";
import Results from "../components/Results";
export class Create extends Component {
constructor(props) {
super(props);
this.state = {
selectedI: { value: "" },
// selectedC: { value: "" },
// selectedG: { value: "" },
// selectedA: { value: "" },
isSubmitted: false,
};
}
handleChange = (event) => {
this.setState({
selectedI: { value: event.target.value },
});
};
handleSubmit = (event) => {
event.preventdefault();
this.setState({
isSubmitted: true,
});
};
render() {
console.log(this.state);
return (
<>
<form onSubmit={this.handleSubmit} onChange={this.handleChange}>
<select value={this.state.value}>
{this.props.ingredient.map((ingredient) => {
return (
<option value={ingredient.strIngredient1}>
{ingredient.strIngredient1}
</option>
);
})}
</select>
<input type="submit" value="Submit" />
</form>
{this.state.isSubmitted && <Results />}
</>
);
}
}
export default Create;
Inside your handleSubmit method correct the case on preventdefault. It should be preventDefault. Note the capital D. Once corrected it should stop your page from reloading and resetting your state along with it. See the code below.
handleSubmit = (event) => {
event.preventDefault();
this.setState({
isSubmitted: true,
});
};

I have two set of input fields for two different forms. How can I use them dynamically for any form?

I am new to react. I am trying to build dynamic form component of a set of input fields using react which can be reused in any single form as a set of inputs. How can I access those input data dynamically?
For example, the form for the set of reusable inputs:
export default class dynamicForm extends Component {
handleSubmit = event => {
// get dynamic input data. But how?
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<CustomInputs1/>
<CustomInputs2/>
<input type="submit" value="confirm"/>
</form>
)}
Input set no. 1 as custom input:
export default class CustomInputs1 extends Component {
constructor(props) {
super(props);
this.state = {
input1: "",
input2: ""
};
this.inputInput1Ref = React.createRef();
this.inputInput2Ref = React.createRef();
}
handleInputChange = event => {
event.preventDefault();
this.setState({
[event.target.name]: event.target.value
});
};
render() {
const { input1 } = this.state;
const { input2 } = this.state;
return (
<div>
<input type="text" name="input1" value={input1} onChange={this.handleInputChange}/>
<input type="text" name="input2" value={input2} onChange={this.handleInputChange}/>
</div>
)
}
}
Input set no. 2 as custom input:
export default class CustomInputs2 extends Component {
constructor(props) {
super(props);
this.state = {
input3: "",
input4: ""
};
this.inputInput3Ref = React.createRef();
this.inputInput4Ref = React.createRef();
}
handleInputChange = event => {
event.preventDefault();
this.setState({
[event.target.name]: event.target.value
});
};
render() {
const { input3 } = this.state;
const { input4 } = this.state;
return (
<div>
<input type="text" name="input3" value={input3} onChange={this.handleInputChange}/>
<input type="text" name="input4" value={input4} onChange={this.handleInputChange}/>
</div>
)
}
}
There can be more reusable input groups like this.I just added two group as example.
A few things: You are not using the refs you are creating in the CustomInputs, so those lines can go. Also, you can destructure the state in one line, like so: const {input1, input2} = this.state.
Now for your problem: You can either create refs to the CustomInputs in your dynamicForm and simply access the state of your custom inputs when the form is submitted or pass a function as props to each CustomInputs which writes the input to the state of dynamicForm. First option is probably easier ;)

React use input vale to search api

React newbie here... I am pulling my hair out trying to figure this out... I am trying to use bandsintown API to search for bands then display the results. I am having a difficult time taking the entered band name and then using that as part of the fetch to the bansintown API. It appears that things are re-rendering or not rendering in the correct order, etc. I have tried putting my call to fetch in componentDidMount but that renders before the 'band' state is set...please help... here is a snippet of my code:
import React, { Component } from "react";
class BandSearch extends Component {
constructor(props) {
super(props);
this.state = {
band: "",
events: []
};
}
componentDidMount() {
this.handleChange();
}
async getBand(e) {
e.preventDefault();
try {
const res = await fetch(
`https://rest.bandsintown.com/artists/${
this.state.band
}/events?app_id=acdb6da27e696632f85c3733dd43db52`
);
const events = await res.json();
this.setState({
events: events
});
} catch (e) {
console.log(e);
}
}
handleChange = () => {
this.setState({
band: this.result.value
});
console.log("state", this.state);
};
render() {
console.log(this.state.band);
return (
<div>
<h3>Enter Band to check on tour dates</h3>
<form>
<input
type="text"
placeholder="Enter band name"
ref={input => (this.result = input)}
onChange={this.handleChange}
/>
<button onClick={this.getBand}>Search</button>
</form>
</div>
);
}
}
export default BandSearch;
Thanks so much in advance!!
You need to pass the event from the onChange event of the input like so:
handleChange = (e) => {
this.setState({
band: e.currentTarget.value
});
// console.log("state", this.state); This will have unexpected results. Try to investigate why.
};
Also remove the call to handleChange in componentDidMount
You are actually missing this binding your function in your constructor.
constructor(props) {
super(props);
this.getBand = this.getBand.bind(this);
this.state = {
band: "",
events: []
};
}
Here is the demo of that: https://stackblitz.com/edit/react-hfkqaw?file=index.js
This is from react
You have to be careful about the meaning of this in JSX callbacks. In
JavaScript, class methods are not bound by default. If you forget to
bind this.handleClick and pass it to onClick, this will be undefined
when the function is actually called.
full reading here: https://reactjs.org/docs/handling-events.html

Resources