Not able to update form data in React - reactjs

I am using react to accept input from the user. And when the user submits I want to get rid of the form and display the user input data.
I am not able to see the user input data on my result page. I have uploaded the screenshots and the code below.
class Form extends React.Component {
constructor(props){
super(props)
this.state = {isFormOn: true, isResult: false , firstname: "", lastname: ""};
this.handleClick = this.handleClick.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleClick(){
this.setState(state => ({
isFormOn: !state.isFormOn,
isResult: !state.isResult
}));
}
handleChange({ event }) {
this.setState({
[event.target.name]: event.target.value
});
}
render(){
return(
<div>
{ this.state.isFormOn && (
<div>
First name :
<input type="text" name="firstname" onChange={this.handleChange} /><br />
Last name :
<input type="text" name="lastname" onChange={this.handleChange} /><br />
<br />
<button onClick={this.handleClick}>
{this.state.isFormOn ? 'ON' : 'OFF'}
</button>
</div>
)}
{ this.state.isResult && (
<div>
<h4>The name entered is : {this.state.firstname} {this.state.lastname} </h4>
<button onClick={this.handleClick}>
{this.state.isFormOn ? 'ON' : 'OFF'}
</button>
</div>
)}
</div>
);
}
}
ReactDOM.render(
<Form />,
document.getElementById('root')
);
Render form to accept user input
Result of the user entered information

Your event handler (handleChange) is destructuring the event object, and trying to extract a property called event from it, which doesn't exist.
You need to use the event object directly instead:
handleChange(event) {
this.setState({
[event.target.name]: event.target.value
});
}

Related

React form error: Form submission canceled because the form is not connected

I have a form inside a class component. When I submit the form, I get a warning Form submission cancelled because the form is not connected. There are no errors—just a warning.
I have linked it to my netlify site. I have added all the form data properties that are required to send the data to netlify.
I have used styled-components for styling.
Not sure, what I am missing.
class ContactThreeForm extends React.Component {
constructor(props) {
super(props);
this.state = {
name: "",
email: "",
phone: "",
message: "",
error: false,
};
}
formSubmit() {
if (
this.state.name === "" ||
this.state.email === "" ||
this.state.phone === "" ||
this.state.message === ""
) {
this.setState({ error: true });
} else {
this.setState({ error: false });
}
this.forceUpdate();
}
check(val) {
if (this.state.error && val === "") {
return false;
} else {
return true;
}
}
render() {
return (
<ContactForm>
<Heading>Get In Touch</Heading>
<Separator />
<form
name="contact"
method="POST"
netlify-honeypot="bot-field"
data-netlify="true"
data-netlify-recaptcha="true"
>
<InputElement>
<Input
type="text"
defaultValue={this.state.name}
className={`name ${this.check(this.state.name) ? "" : "error"}`}
placeholder="Name"
onChange={(e) => this.setState({ name: e.target.value })}
/>
</InputElement>
<InputElement>
<Input
type="text"
defaultValue={this.state.email}
className={`email ${this.check(this.state.email) ? "" : "error"}`}
placeholder="Email"
onChange={(e) => this.setState({ email: e.target.value })}
/>
</InputElement>
<InputElement>
<Input
type="text"
defaultValue={this.state.phone}
className={`phone ${this.check(this.state.phone) ? "" : "error"}`}
placeholder="Phone"
onChange={(e) => this.setState({ phone: e.target.value })}
/>
</InputElement>
<InputElement>
<Textarea
placeholder="Message"
defaultValue={this.state.message}
className={`message ${
this.check(this.state.message) ? "" : "error"
}`}
onChange={(e) => this.setState({ message: e.target.value })}
/>
</InputElement>
<Submit onClick={() => this.formSubmit()}>
<span>Submit</span>
</Submit>
</form>
</ContactForm>
);
}
}
The browser's default handling of a form submission is to make an HTTP POST request to the server and reload the page with whatever is in the response (which may or may not even be content the browser can render). This is almost never what you want in a single page application, because your entire app and all of its state is simply discarded.
Instead of wiring up the form submit as a click handler on the submit button, you should instead wire it up as the onSubmit event of the form. You also want to call preventDefault() on the event, which prevents the native browser behavior. The button doesn't need a click handler at all as long as it has the attribute type="submit" (presumably, inside of your Submit component, there is a regular button element).
formSubmit(event) {
event.preventDefault();
// your submit logic
}
render() {
// ...
<form onSubmit={(event) => this.formSubmit(event)}
// ... Inside `Submit` should be something like:
<button type="submit" />
</form>
}

Reactjs : TypeError: Cannot read property 'value' of undefined

I am new to Reactjs and trying to change the of value text which is entered by user in textbox, after button click event.
But after button click event I am getting error "TypeError: Cannot read property 'value' of undefined" at handleChange(e) function.Can anyone please help me with whats going wrong here??
Here is the component I am working with :
Constructor(props){
super();
this.state={
typedtext: 'Nothing'
}
};
handleClick(){
this.handleChange(this.state.typedtext)
}
handleChange(e){
this.setState({ typedtext: e.target.value });
}
render(){
return(
<div>
<label> Typed Value is : {this.state.typedtext} </label> <p>
</p>
<label> Type Something here </label>
<input type='text'onChange={(e)=>this.handleChange(e)}
value= {this.state.typedtext}/>
<button onClick={()=>this.handleClick()}> Copy Text </button>
</div>
);
}
}
The problem appears because when you run handleChange in handleClick method you use the value of your state as the argument instead of event object. It is trying to get value property of string.
Your code should look like this:
constructor(props) {
super(props);
this.state = {
typedtext: 'Nothing'
}
};
handleClick(e) {
this.handleChange(e)
}
handleChange(e) {
this.setState({
typedtext: e.target.value
});
}
render() {
return (
<div>
<label> Typed Value is : {this.state.typedtext} </label>
<p></p>
<label> Type Something here </label>
<input type='text'onChange={e => this.handleChange(e)} value={this.state.typedtext}/>
<button onClick={e => this.handleClick(e)}> Copy Text </button>
</div>
);
}
But handleClick will not copy the text. It will just remove it because handleChange will try to get the value of button that doesn't contain any value.
Working code looks like this:
constructor(props) {
super(props);
this.state = {
typedtext: 'Nothing'
}
};
handleChange() {
this.setState({
typedtext: this.input.value
});
}
render() {
return (
<div>
<label> Typed Value is : {this.state.typedtext} </label>
<p></p>
<label> Type Something here </label>
<input type='text'onChange={() => this.handleChange()} value={this.state.typedtext} ref={input => this.input = input}/>
<button onClick={() => this.handleChange()}> Copy Text </button>
</div>
);
}
But you will not be able to see what the button does because while you are typing it already copies the text. :)
Try to add a bind to "this" refering this method on contructor:
this.handleChange = this.handleChange.bind(this)
The entire code on constructor:
constructor(props){
super();
this.state={
typedtext: 'Nothing'
}
this.handleChange = this.handleChange.bind(this)
};

How to dynamically generate pair of input fields using reactjs

I have tried the following code to create a react form to dynamically generate input fields to enter the series of person's name one by one. But user needs to enter the first name and last name instead of just name. So that, the form needs to generate pair of dynamic input fields. I am new to react. Can anyone please give an hint on how to accomplish this.
Note : The following code has been taken from the stackoverflow answer of #Mayank Shukla at How to implement a dynamic form with controlled components in React.JS?.
class App extends React.Component {
constructor(props) {
super(props);
this.state = { values: [] };
this.handleSubmit = this.handleSubmit.bind(this);
}
createUI(){
return this.state.values.map((el, i) =>
<div key={i}>
<input type="text" value={el||''} onChange={this.handleChange.bind(this, i)} />
<input type='button' value='remove' onClick={this.removeClick.bind(this, i)}/>
</div>
)
}
handleChange(i, event) {
let values = [...this.state.values];
values[i] = event.target.value;
this.setState({ values });
}
addClick(){
this.setState(prevState => ({ values: [...prevState.values, '']}))
}
removeClick(i){
let values = [...this.state.values];
values.splice(i,1);
this.setState({ values });
}
handleSubmit(event) {
alert('A name was submitted: ' + this.state.values.join(', '));
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
{this.createUI()}
<input type='button' value='add more' onClick={this.addClick.bind(this)}/>
<input type="submit" value="Submit" />
</form>
);
}
}
ReactDOM.render(<App />, document.getElementById('container'));
Idea is, maintain an array of object in state variable. Each object will have two keys firstName and secondName (you can add more fields). Treat each object as a single unit and for all the keys render input element, and whenever user will click on add more, add one more object/entry the the array with two keys.
Working Fiddle.
Working Snippet:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
users: [{firstName: "", lastName: ""}]
};
this.handleSubmit = this.handleSubmit.bind(this);
}
addClick(){
this.setState(prevState => ({
users: [...prevState.users, { firstName: "", lastName: "" }]
}))
}
createUI(){
return this.state.users.map((el, i) => (
<div key={i}>
<input placeholder="First Name" name="firstName" value={el.firstName ||''} onChange={this.handleChange.bind(this, i)} />
<input placeholder="Last Name" name="lastName" value={el.lastName ||''} onChange={this.handleChange.bind(this, i)} />
<input type='button' value='remove' onClick={this.removeClick.bind(this, i)}/>
</div>
))
}
handleChange(i, e) {
const { name, value } = e.target;
let users = [...this.state.users];
users[i] = {...users[i], [name]: value};
this.setState({ users });
}
removeClick(i){
let users = [...this.state.users];
users.splice(i, 1);
this.setState({ users });
}
handleSubmit(event) {
alert('A name was submitted: ' + JSON.stringify(this.state.users));
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
{this.createUI()}
<input type='button' value='add more' onClick={this.addClick.bind(this)}/>
<input type="submit" value="Submit" />
</form>
);
}
}
ReactDOM.render(<App />, document.getElementById('container'));
<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="container" />
Try this
state = {
number: [""],
dataArr: []
}
render() {
return (
<div>
<div onClick={()=>this.setState(prevState => ({number: [...prevState.number, ""]}))}>Add More element</div>
{this.state.number.map((e, i)=> {
return (
<input value={this.state.number[i]} onChange={(data) => this.setState({dataArr: update(this.state.dataArr, {i: {$set: data}})})} />
)
})}
</div>
)
}
You will have to handle the data inside this.state.dataArr. For instance, this.state.dataAtt[0] will contain the starting value in input field before user presses "Add More Element" button and then when user presses the same button again data will be added in this.state.dataArr[1] and so on.
You will need react-addons-update lib.

ReactJS - pass input values from child to parent

child component
import React, { Component } from 'react'
export default class Login extends Component {
constructor (props) {
super(props);
this.state = {Id: '',name: '',gender: ''};
this.show = this.show.bind(this);
}
show (event) {
if (this.state.Id === "123456" && this.state.name !== '' && this.state.gender !== '') {
this.props.show();
alert('you are login');
console.log('A ID was submitted: ' + this.state.Id);
console.log('A Name was submitted: ' + this.state.name);
console.log('A Gender was submitted: ' + this.state.gender);
} else {
alert('Please enter your valid id,Your Name & Gender');
}
event.preventDefault();
}
render () {
return (
<div className="login">
<form onSubmit={ this.show.bind(this) }>
<div>
<label>Your ID:</label>
<input type="text" onChange={ event => this.setState({ Id: event.target.value }) } placeholder="Enter your ID" />
</div>
<br />
<div>
<label>Your Name:</label>
<input type="text" onChange={ event => this.setState({ name: event.target.value }) } placeholder="Enter your Name" />
</div>
<br />
<div>
<label>Your Gender:</label>
<label>Female:</label>
<input type="radio" name="gender" value="Female" onChange=
{ event => this.setState({ gender: event.target.value }) } />
<label>Male:</label>
<input type="radio" name="gender" value="Female" onChange={ event => this.setState({ gender: event.target.value }) } />
</div>
<input type="submit" value="Submit" onClick={ this.props.comingvalue } />
</form>
</div>
)
}
}
parent component
class App extends Component {
constructor (props) {
super(props);
this.state = { Id: '', name: '', gender: '' };
}
getvalue () {
console.log('getting values as props');
this.setState({ Id: this.state.Id });
this.setState({ name: this.state.name });
this.setState({ gender: this.state.gender });
}
render () {
return (
<div className="App">
<Login comingvalue={ this.getvalue } />
<button type="button" className="btn btn-primary" onClick=
{ this.handleLogin }>Sign In</button>
</div>
);
}
}
export default App;
now here is the my question i want that when i enter value in my child component i get those values in parent compnent how i can get this please help..'i thing you peeple should know that i cut alot of code from above code there is possibilty of any other error but i want to know only one thing which i mention above i want child coponents value in parent component.. please suggest me right solution..thanks
Just a pointer for future posts: the less code the better and please, for the love of God, make sure the formatting is correct.
A standard pattern in React for passing information back up the tree is to pass children a callback as a prop.
parent
class Parent extends React.Component {
onChildCallback = (data) => {
alert(data)
}
render() {
return (
<div>
...
<Child onAction={this.onChildCallback}/>
</div>
)
}
}
child
class Child extends React.Component {
render() {
return (
<button onClick={() => this.props.onAction('hello from the child')}>
Click Me!
</button>
)
}
}
this is, of course, simplified, but you can extend it however you like. Some things to watch out for:
make sure you're either binding the callback in the parent or using arrow functions (in this case, I'm using a ES7 class property)
if you need data from a child of a child, you need to chain these... you can get away with using context, but ... don't. Just don't.

How to fetch input from text box and print in React?

I am new to React trying to write a very simple project that fetches input of both text boxes and when button is clicked, the 'data' in text boxes is printed on paragraph.
How do I fetch text's in input text boxes when button is clicked?
class Input extends Component {
state = {
tagged: false,
message: '',
}
handleClick(e) {
this.setState({tagged: true});
e.preventDefault();
console.log('The link was clicked.');
}
render() {
return (
<div id="id" style={divStyle}>
<p> hello </p>
<input
style = {textStyle}
placeholder="user#email.com"
type="text">
</input>
<input
style = {textStyle}
placeholder="tag"
type="text">
</input>
<button
onClick={(e) => this.handleClick(e)}
style={buttonStyle}>
{this.state.tagged ? 'Tagged' : 'Tag ' }
</button>
<p>
{this.state.tagged ? 'Clicked' : 'Still' }
</p>
</div>
)
}
}
You can add onChange event handler in each input.
class Input extends Component {
state = {
tagged: false,
message: '',
input1: '',
input2: '',
}
handleClick(e) {
// access input values in the state
console.log(this.state) // {tagged: true, input1: 'text', input2: 'text2'}
this.setState({tagged: true});
e.preventDefault();
console.log('The link was clicked.');
}
handleInputChange = (e, name) => {
this.setState({
[name]: e.target.value
})
}
render() {
return (
<div id="id" style={divStyle}>
<p> hello </p>
<input
style = {textStyle}
placeholder="user#email.com"
type="text"
onChange={(e) => this.handleInputChange(e, 'input1')}
>
</input>
<input
style = {textStyle}
placeholder="tag"
type="text"
onChange={(e) => this.handleInputChange(e, 'input2')}
>
</input>
<button
onClick={(e) => this.handleClick(e)}
style={buttonStyle}>
{this.state.tagged ? 'Tagged' : 'Tag ' }
</button>
<p>
{this.state.tagged ? 'Clicked' : 'Still' }
</p>
</div>
)
}
}
There are two different ways of working with react inputs - you can either make them controlled or uncontrolled. When you say fetch text from inputs, this is called uncontrolled components and means that form data is handled by the DOM itself and not by react.
This is achieved by using ref and literally getting a reference to your input and fetching its value when you need it. you can read more about this approach in react docs.
According to react docs, it is recommended using controlled components
In most cases, we recommend using controlled
components to implement forms. In a controlled
component, form data is handled by a React component.
This means that you don’t use references to the inputs and instead handle changes of your inputs with an event handler and update state with the new values that the user has entered into the input fields. According to react docs here is how react handles form with controlled components:
the React component that
renders a form also controls what happens in that form on subsequent
user input. An input form element whose value is controlled by React in this way is called a “controlled component”.
In your case you can do this if you choose controlled inputs:
class ControlledInput extends React.Component {
constructor(props) {
super(props);
this.state = {
tagged: false,
firstInput: '',
secondInput: ''
}
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({ [event.target.name]: event.target.value });
}
handleClick(e) {
this.setState({ tagged: true });
e.preventDefault();
console.log('The link was clicked.');
}
render() {
const { firstInput, secondInput, tagged } = this.state;
return (
<div id="id">
{tagged && <p>{firstInput} {secondInput}</p> }
<input
value={firstInput}
name="firstInput"
onChange={this.handleChange}
type="text" />
<input
value={secondInput}
name="secondInput"
onChange={this.handleChange}
type="text" />
<button onClick={(e) => this.handleClick(e)}>
{tagged ? 'Tagged' : 'Tag '}
</button>
</div>
)
}
}
Here you put the inputs' values on state and update state when the user writes something in your inputs. If you however want to use uncontrolled components you can do it this way:
class UncontrolledInput extends React.Component {
state = {
tagged: false,
message: '',
}
handleClick(e) {
e.preventDefault();
const messageFromInputs = `${this.firstInput.value} ${this.secondInput.value}`;
this.setState({ tagged: true, message: messageFromInputs });
}
render() {
return (
<div id="id">
<p>{this.state.message}</p>
<input ref={(input) => this.firstInput = input} type="text" />
<input ref={(input) => this.secondInput = input} type="text" />
<button onClick={(e) => this.handleClick(e)}>
{this.state.tagged ? 'Tagged' : 'Tag '}
</button>
<p>
{this.state.tagged ? 'Clicked' : 'Still'}
</p>
</div>
)
}
}
Here you will actually fetch values from your inputs when the button is clicked.
I made a working example with both ways on codesandbox.

Resources