How to use the info from a component on another component - javascript

I am trying to create a payment system in my application.
I have a payment form(paymentForm.js) and it contains the payment information(cardnumber, cvv, expiry...). Is there any way that I can get these information on another component(checkoutPage.js)? Do you have any advice?
Below is my paymentForm.js:
export default class PaymentForm extends React.Component {
state = {
cvv: '',
expiry: '',
focus: '',
name: '',
number: '',
};
handleInputFocus = (e) => {
this.setState({ focus: e.target.name });
}
handleInputChange = (e) => {
const { name, value } = e.target;
this.setState({ [name]: value });
}
render() {
return (
<View>
<Cards id="PaymentForm"
cvc={this.state.cvc}
expiry={this.state.expiry}
focused={this.state.focus}
name={this.state.name}
number={this.state.number}
/>
<form style={{}}>
<input
type="tel"
name="number"
placeholder="Card Details"
maxLength="16"
preview='true'
onChange={this.handleInputChange}
onFocus={this.handleInputFocus}
/>
<br/>
<input
type="text"
name="name"
placeholder="Holder Name"
onChange={this.handleInputChange}
onFocus={this.handleInputFocus}
/>
<br/>
<input
type="tel"
name="expiry"
placeholder="Expiration"
maxLength="4"
onChange={this.handleInputChange}
onFocus={this.handleInputFocus}
/>
<br/>
<input
type="tel"
name="cvc"
placeholder="CVV"
maxLength="5"
onChange={this.handleInputChange}
onFocus={this.handleInputFocus}
/>
<br/>
<input
type="tel"
name="zipcode"
placeholder="ZIP Code"
maxLength="5"
onChange={this.handleInputChange}
onFocus={this.handleInputFocus}
/>
</form>
</View>
);
}
}

You should create a file CheckOut.js and give card information via props. There is also another way to do it by creating a class named 'Checkout' and creating static methods inside.

Related

Setting formData with an object

Currently, i have this state with a formData.
Upon typing some text, instead to change the fullName.firstName. its making another property and just setting a single (as in single letter) value.
const [formData, setFormData] = useState({
fullName: {
firstName: "",
lastName: "",
},
email: "",
password: "",
confirmPassword: "",
});
This is how i set the formData.
const handleChange = (event) => {
const { value, name } = event.target;
console.log(name, value);
setFormData((prevFormData) => ({
...prevFormData,
[name]: value,
}));
};
This is my JSX, you may check the "name" attribute in input for some reference.
<div className="App">
<form onSubmit={onSubmit}>
<h1>Submit Form Nested Object UseState</h1>
<input
text="text"
placeholder="First Name"
name="firstName"
value={formData.fullName.firstName}
onChange={handleChange}
/>
<input
text="text"
placeholder="Last Name"
name="lastName"
value={formData.fullName.lastName}
onChange={handleChange}
/>
<input
text="email"
placeholder="email"
name="email"
value={formData.email}
onChange={handleChange}
/>
<input
text="password"
placeholder="password"
name="password"
value={formData.password}
onChange={handleChange}
/>
<input
text="password"
placeholder="confirm Password"
name="confirmPassword"
value={formData.confirmPassword}
onChange={handleChange}
/>
<button>Submit</button>
</form>
{JSON.stringify(formData, null, 2)}
</div>
Change the form names like so:
<form onSubmit={onSubmit}>
<h1>Submit Form Nested Object UseState</h1>
<input
placeholder="First Name"
name="fullName.firstName"
value={formData.fullName.firstName}
onChange={handleChange}
/>
<input
placeholder="Last Name"
name="fullName.lastName"
value={formData.fullName.lastName}
onChange={handleChange}
/>
<input
placeholder="email"
name="email"
value={formData.email}
onChange={handleChange}
/>
<input
placeholder="password"
name="password"
value={formData.password}
onChange={handleChange}
/>
<input
placeholder="confirm Password"
name="confirmPassword"
value={formData.confirmPassword}
onChange={handleChange}
/>
<button>Submit</button>
</form>
then change your handleChange function to this:
const handleChange = (event) => {
const { value } = event.target;
const [key,subkey] = event.target.name.split('.');
setFormData((prevFormData) => ({
...prevFormData,
[key]: subkey ? {
...prevFormData[key],
[subkey]: value,
} : value
}));
};

how to set props values of controls in react js

I am new to react. I have almost 15 input controls on UI. Some are dropdowns, some are textboxes, couple of calender controls and radio buttons. I want to retrive all values before submitting a page. Do I need to define 15 props in state object of component for 15 inputs? is there any way to have it in one object.
Also how to set the values of each control. For example for textbox I know, its like
<input type="text" name="username" className="form-control" id="exampleInput" value={this.props.name} onChange={this.handleChange} placeholder="Enter name"></input>
How to handle same for dropdown,calender and radio buttton. Thanks in advance.
Normally, these wouldn't be props, they'd be state (which is different). You can use objects in state. If you're doing a class-based component (class YourComponent extends React.Component), state is always an object you create in the constructor and update with setState. If you're doing this in a function component, typically you use separate state variables for each thing (const [name, setName] = useState("");), but you can use an object if you prefer. There's more about state in the documentation.
That said, if you only want the values when you take an action, you could make the inputs "uncontrolled."
Here's a three-input example using a class component:
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
firstName: "",
lastName: "",
about: ""
};
this.handleChange = this.handleChange.bind(this);
}
handleChange({target: {name, value}}) {
this.setState({[name]: value});
}
render() {
const {firstName, lastName, about} = this.state;
const {handleChange} = this;
return <div>
<div>
<label>
First name:
<br/>
<input type="text" value={firstName} name="firstName" onChange={handleChange} />
</label>
</div>
<div>
<label>
Last name:
<br/>
<input type="text" value={lastName} name="lastName" onChange={handleChange} />
</label>
</div>
<div>
<label>
About you:
<br />
<textarea value={about} name="about" onChange={handleChange} />
</label>
</div>
<div>{firstName} {lastName} {(firstName || lastName) && about ? "-" : ""} {about}</div>
</div>;
}
}
ReactDOM.render(<Example/>, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
Here's one using a functional component with discrete state items (usually best):
const { useState } = React;
const Example = () => {
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [about, setAbout] = useState("");
// There's are lots of ways to do this part, this is just one of them
const handleChange = ({target: {name, value}}) => {
switch (name) {
case "firstName":
setFirstName(value);
break;
case "lastName":
setLastName(value);
break;
case "about":
setAbout(value);
break;
}
};
return <div>
<div>
<label>
First name:
<br/>
<input type="text" value={firstName} name="firstName" onChange={handleChange} />
</label>
</div>
<div>
<label>
Last name:
<br/>
<input type="text" value={lastName} name="lastName" onChange={handleChange} />
</label>
</div>
<div>
<label>
About you:
<br />
<textarea value={about} name="about" onChange={handleChange} />
</label>
</div>
<div>{firstName} {lastName} {(firstName || lastName) && about ? "-" : ""} {about}</div>
</div>;
}
ReactDOM.render(<Example/>, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
Here's one using a functional component with an object in state:
const { useState } = React;
const Example = () => {
const [data, setData] = useState({firstName: "", lastName: "", about: ""});
const handleChange = ({target: {name, value}}) => {
setData(current => ({...current, [name]: value}));
};
const {firstName, lastName, about} = data;
return <div>
<div>
<label>
First name:
<br/>
<input type="text" value={firstName} name="firstName" onChange={handleChange} />
</label>
</div>
<div>
<label>
Last name:
<br/>
<input type="text" value={lastName} name="lastName" onChange={handleChange} />
</label>
</div>
<div>
<label>
About you:
<br />
<textarea value={about} name="about" onChange={handleChange} />
</label>
</div>
<div>{firstName} {lastName} {(firstName || lastName) && about ? "-" : ""} {about}</div>
</div>;
}
ReactDOM.render(<Example/>, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
Here is the sample code, I used in my application.
class CreditCardForm extends React.Component {
constructor() {
super()
this.state = {
name: '',
address: '',
ccNumber: ''
}
}
handleChange(e) {
// If you are using babel, you can use ES 6 dictionary syntax
// let change = { [e.target.name] = e.target.value }
let change = {}
change[e.target.name] = e.target.value
this.setState(change)
}
render() {
return (
<form>
<h2>Enter your credit card details</h2>
<label>
Full Name
<input type="name" onChange={(e)=>this.handleChange(e)} value={this.state.name} />
</label>
<label>
Home address
<input type="address" onChange={(e)=>this.handleChange(e)} value={this.state.address} />
</label>
<label>
Credit card number
<input type="ccNumber" onChange={(e)=>this.handleChange(e)} maxlength="16" value={this.state.ccNumber} />
</label>
<button type="submit">Pay now</button>
</form>
)
}
}
You can set name for input and update state base on event.target.name and event.target.value
constructor() {
super();
this.state = {
text: "",
select: "",
radio: ""
};
}
handeInput = e => {
this.setState({
[e.target.name]: e.target.value
});
};
render() {
console.log(this.state);
return (
<div className="App">
<input
onChange={this.handeInput}
type="input"
name="text"
value={this.state.text}
/>
<select
name="select"
onChange={this.handeInput}
value={this.state.select}
>
<option value="option1">option1</option>
<option value="option2">option2</option>
</select>
<input
type="radio"
name="radio"
value="Option1"
checked={this.state.radio === "Option1"}
onChange={this.handeInput}
/>
Option1
<input
type="radio"
name="radio"
value="Option2"
checked={this.state.radio === "Option2"}
onChange={this.handeInput}
/>
Option2
</div>
);
}
You can check here CodeSandBox Hope it helps

Storing each input's data in its respective state

I have three inputs, and I want each input's data to be stored in a state. For example, the name input should be stored in the name state, because I'll need it later to push the three states' values in a firebase database.
I used the onChange function to store the data, but I didn't know how to make each input's function relative to the state I want to put it in.
import React from "react";
import ReactDOM from "react-dom";
export default class Inputs extends React.Component {
constructor(props) {
super(props);
this.state = {
name: "",
email: "",
age: ""
};
}
handleChange = e => {
this.setState({ name: e.target.value });
};
render() {
return (
<div>
<form>
<label>
name:
<input type="text" name="name" onChange={this.handleChange} />
</label>
<label>
email:
<input type="text" name="email" onChange={this.handleChange} />
</label>
<label>
age:
<input type="text" name="age" onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
<textarea value={this.state.value} onChange={this.handleChange} />
<button onClick={() => this.props.onClick(this.state.value)}>
Add task
</button>
</div>
);
}
}
getChanges = (e) => {
console.log(e);
this.setState({[e.target.name]: e.target.value}, function () {
console.log(this.state)
})
};
call this function,
<Input onChange={(e) => this.getChanges(e)} name={'name'}
value={this.state.name} placeholder={'Name'}/>
You can pass key and value
<input type="text" name="name" onChange={(event)=>this.handleChange(event,'name')} />
and in your function you can do something like this
handleChange = (e,key) => {
this.setState({ [key] : e.target.value });
};

React event.target is undefined for only one input element

I'm new to React and have run into a problem building a simple form component. There are four input fields and four matching onChange handlers. All of them are effectively identical:
handleEmailChange(event) {
this.setState({email: event.target.value});
}
handlePasswordChange(event) {
this.setState({password: event.target.value});
}
handleFirstNameChange(event) {
this.setState({firstName: event.target.value});
}
handleLastNameChange(event) {
this.setState({lastName: event.target.value});
}
render() {
return (
<div>
<label>Email: </label>
<input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleEmailChange} />
<label>Password: </label>
<input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handlePasswordChange} />
<label>First name: </label>
<input type="text" name="firstName" placeholder="First name" value={this.state.firstName} onChange={this.handleFirstNameChange} />
<label>Last name: </label>
<input type="text" name="lastName" placeholder="Last name" value={this.state.lastName} onChange={this.handleLastNameChange} />
<input type="submit" value="Add User" onClick={this.handleSubmit} />
</div>
)
}
Three of these work just fine. The password handler, however, throws a TypeError exception "event.target is undefined" when the page tries to render. If I remove the handler and input element, the app renders. If I copy and paste one of the other handlers and inputs and change the relevant names, it still throws the exception. If I change the input type from "password" to "text" it still throws the exception. I cannot figure out why a seemingly identical piece of code is throwing this exception but every other piece of code like it works just fine.
In case it matters, the code for the entire component is
class AddUserForm extends Component {
constructor(props) {
super(props);
this.state = {
email: '',
password: '',
firstName: '',
lastName: ''
};
this.validate = this.validate.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleEmailChange = this.handleEmailChange.bind(this);
this.handlePasswordChange = this.handlePasswordChange(this);
this.handleFirstNameChange = this.handleFirstNameChange.bind(this);
this.handleLastNameChange = this.handleLastNameChange.bind(this);
}
validate(user) {
return (user.email && user.password && user.firstName && user.lastName);
}
handleSubmit(event) {
let newUser = {
email: this.state.email,
password: this.state.password,
firstName: this.state.firstName,
lastName: this.state.lastName
};
if (AddUserForm.validate(newUser)) {
fetch(`http://localhost:3001/admin/addUser`, {
method: 'post',
headers: new Headers({
'Content-Type': 'application/x-www-form-urlencoded',
}),
body: JSON.stringify(newUser)
})
.then( res => {
const copy = [newUser].concat(this.state.users);
this.setState({users: copy});
})
}
event.preventDefault();
}
handleEmailChange(event) {
this.setState({email: event.target.value});
}
handlePasswordChange(event) {
this.setState({password: event.target.value});
}
handleFirstNameChange(event) {
this.setState({firstName: event.target.value});
}
handleLastNameChange(event) {
this.setState({lastName: event.target.value});
}
render() {
return (
<div>
<label>Email: </label>
<input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleEmailChange} />
<label>Password: </label>
<input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handlePasswordChange} />
<label>First name: </label>
<input type="text" name="firstName" placeholder="First name" value={this.state.firstName} onChange={this.handleFirstNameChange} />
<label>Last name: </label>
<input type="text" name="lastName" placeholder="Last name" value={this.state.lastName} onChange={this.handleLastNameChange} />
<input type="submit" value="Add User" onClick={this.handleSubmit} />
</div>
)
}
}
You are invoking handlePasswordChange in the constructor by writing handlePasswordChange(this). You want to bind it to this instead.
this.handlePasswordChange = this.handlePasswordChange.bind(this);

Not hitting `debugger` statement in `handleOnSubmit`

I'm having a pretty specific problem in my React with Rails API backend app. I have a Redux form that I am using to create a new object, a real estate listing. The state is changing in my onChange function but when I click submit, the page refreshes and nothing was created. I put debugger inside my handleOnSubmit and it’s not hitting, any ideas?
ListingForm.js:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { updateListingFormData } from '../actions/listingForm';
import { createListing } from '../actions/listings';
class ListingForm extends Component {
handleOnChange = event => {
const { name, value } = event.target;
const currentListingFormData = Object.assign({}, this.props.listingFormData, {
[name]: value
})
this.props.updateListingFormData(currentListingFormData)
}
handleOnSubmit = (event) => {
debugger;
event.preventDefault()
this.props.createListing(this.props.listingFormData)
}
render() {
const { title, price, location, description, img_url, agent_name, agent_number, agent_email } = this.props.listingFormData;
return (
<div className="ListingForm">
<h3>Add New Listing</h3>
<form onSubmit={(event) => this.handeOnSubmit(event)}>
<label htmlFor="listing_title">Title</label>
<input
type="text"
name="title"
value={title}
onChange={(event) => this.handleOnChange(event)}
placeholder="Listing Title"
/>
<label htmlFor="listing_location">Location</label>
<input
type="text"
name="location"
value={location}
onChange={(event) => this.handleOnChange(event)}
placeholder="Listing City or County"
/>
<label htmlFor="listing_price">Price</label>
<input
type="integer"
name="price"
value={price}
onChange={(event) => this.handleOnChange(event)}
placeholder="Listing Price"
/>
<label htmlFor="listing_description">Description</label>
<input
type="text"
name="description"
value={description}
onChange={(event) => this.handleOnChange(event)}
placeholder="Listing Description"
/>
<label htmlFor="listing_image">Attach Image</label>
<input
type="text"
name="img_url"
value={img_url}
onChange={(event) => this.handleOnChange(event)}
placeholder="Listing Image"
/>
<label htmlFor="agent_name">Listing Agent</label>
<input
type="text"
name="agent_name"
value={agent_name}
onChange={(event) => this.handleOnChange(event)}
placeholder="Agent Name"
/>
<label htmlFor="agent_number">Listing Agent Phone</label>
<input
type="text"
name="agent_number"
value={agent_number}
onChange={(event) => this.handleOnChange(event)}
placeholder="Agent Phone"
/>
<label htmlFor="agent_email">Agent Email</label>
<input
type="text"
name="agent_email"
value={agent_email}
onChange={(event) => this.handleOnChange(event)}
placeholder="Agent Email"
/>
<button type="submit"> Add Listing</button>
</form>
</div>
)
}
}
const mapStateToProps = state => {
return {
listingFormData: state.listingFormData
}
}
export default connect(mapStateToProps, {updateListingFormData,createListing})(ListingForm);
In your form onSubmit you've misspelt handleOnSubmit (you left out the l)

Categories