I am quite new in React and I've been stuck in this problem. When I send email address to mailchimp, I have still this address after sending. I tried to fix it but it's just a mess.
class Newsletter extends React.Component {
constructor(props) {
super(props);
this.state = {
email: ''
};
mySubmitHandler = (event) => {
event.preventDefault();
this.setState({email: ''});
}
render() {
return (
<form className="newsletter_form" onSubmit={this.mySubmitHandler} value={this.state.email}>
<h1 style={{fontSize: 40, paddingTop: '10px'}}>Newsletter</h1>
<p className="newsletter_info">Stay up to date with dance news in Oslo with us</p>
<MailchimpSubscribe value="subscribe" url={process.env.REACT_APP_MAILCHIMP_URL} />
<p className="newsletter_info">Your email is safe with us.</p>
<p className="newsletter_info"> We don't spam.</p>
</form>
)
}
};
export default Newsletter;
I fixed this problem by adding:
class Newsletter extends React.Component {
constructor(props) {
super(props);
this.state = {
email: ''
};
}
mySubmitHandler = (event) => {
event.preventDefault();
event.target.reset();
}
render() {
return (
<form className="newsletter_form" onSubmit={this.mySubmitHandler.bind(this)}>
but thanks! :)
By using a good tool for handling form data you can have a more readable and clean code.
import React from "react";
import { useForm } from "react-hook-form";
const Newsletter App() {
const {
reset, register, handleSubmit, formState: { errors }
} = useForm();
const onSubmit = data => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<button type="button" onClick={reset}>x</button>
<input defaultValue="test" {...register("example")} />
<input {...register("exampleRequired", { required: true })} />
{errors.exampleRequired && <span>This field is required</span>}
<input type="submit" />
</form>
);
}
export default Newsletter;
Related
might seem awkward right, but i simply did equalize the value attribute of input tag into some random state. but i simply cant even type into the input. the input is supposed to be emptied after click but well, nothing is happening. (sorry if this question is asked before, im really going crazy and couldnt find anything on google which helps me)
import React from 'react';
import './App.css';
class App extends React.Component{
constructor(){
super()
this.state ={
address : "",
name:"",
main : {
},
// city:undefined,
inputval: "",
}
}
handleName = (event) => {
this.setState({name: event.target.value})
}
handleAdd = (event) => {
this.setState({address: event.target.value})
}
handleClick = (event) => {
event.preventDefault()
this.setState({main:{
address: this.state.address,
name: this.state.name,
}})
this.setState({inputval:""})
}
render(){
return(
<div>
<form>
<input value={this.state.inputval} type="text" onChange={(e) => {this.handleName(e)}}/>enter full name
<br/>
<input value={this.state.inputval} type="text" onChange={(e) => {this.handleAdd(e)}}/> enter adresss
<br/>
<button onClick={(e) => {this.handleClick(e)}}>Click me</button>
</form>
</div>
)
}
}
export default App;
import React from "react";
class App extends React.Component {
constructor() {
super();
this.state = {
address: "",
name: ""
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
const { name, value } = event.target;
this.setState({
[name]: value
});
}
handleSubmit(event) {
event.preventDefault();
alert("A name was submitted: " + this.state.name);
this.setState({
address: "",
name: ""
});
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input
value={this.state.name}
name="name"
type="text"
onChange={this.handleChange}
/>
enter full name
<br />
<input
value={this.state.address}
name="address"
type="text"
onChange={this.handleChange}
/>{" "}
enter adresss
<br />
<input type="submit" value="Submit" />
</form>
</div>
);
}
}
export default App;
Add name attributes to write only one change handler. It makes it so easier. I hope it helps. Look I wrote again setState to reset after submitting
You are not changing inputval at all. If you want to reset the form after button change. Then below is the solution
import React from 'react';
import './App.css';
class App extends React.Component{
constructor(){
super()
this.state ={
address : "",
name:"",
main : {
},
// city:undefined,
inputval: "",
}
this.handleName = this.handleName.bind(this)
this.handleAdd = this.handleAdd.bind(this)
this.handleClick = this.handleClick.bind(this)
}
handleName = (event) => {
this.setState({name: event.target.value})
}
handleAdd = (event) => {
this.setState({address: event.target.value})
}
handleClick = (event) => {
event.preventDefault()
this.setState({main:{
address: this.state.address,
name: this.state.name,
}})
this.setState({
address: "",
name: ""
})
}
render(){
return(
<div>
<form>
<input value={this.state.name} type="text" onChange={(e) => {this.handleName(e)}}/>enter full name
<br/>
<input value={this.state.address} type="text" onChange={(e) => {this.handleAdd(e)}}/> enter adresss
<br/>
<button onClick={(e) => {this.handleClick(e)}}>Click me</button>
</form>
</div>
)
}
}
export default App;
Here is my simple to-do app program where I have made only one component which takes in the input form user and passes that input value to App.js to update items in App.js state.
todo-form.component.js
import React from 'react';
class SignInForm extends React.Component {
constructor(){
super();
this.state ={
temp: null
};
}
handleChange = (e) => {
e.preventDefault();
this.setState({
temp: e.target.value
},
console.log(this.state)
);
// this.props.addInput(e.target.value);
}
handleSubmit= (e) => {
e.preventDefault();
console.log(this.state.temp);
this.props.addInput(this.state.temp);
}
render(){
return(
<div className="container-form">
<form onSubmit={this.handleSubmit}>
<input
name="description"
type="text"
placeholder="add description"
onChange={this.handleChange}
value={this.state.input}
/>
<button type="submit">ADD</button>
</form>
</div>
);
}
}
export default SignInForm;
App.js
import React from 'react';
import './App.css';
import SignInForm from './components/todo-form/todo-form.component'
import ItemList from './components/todo-list/todo-list.component';
class App extends React.Component {
constructor(){
super();
this.state = {
input: []
};
}
addInput = (item) => {
let newInput=[...this.state.input,item];
console.log(newInput);
this.setState = ({
input: newInput
},
console.log(this.state)
);
}
render(){
return (
<div className="App">
<h1>TO-DO LIST</h1>
<SignInForm addInput={this.addInput} />
</div>
);
}
}
export default App;
On taking input the state inside todo-form.component.js is getting updated with the typed input value but on passing state.temp in handleChange function, the state inside App.js is not updating when addInput function is called.
Please help me on this issue and how my state is not getting updated in App.js??
Your setState is the problem. Have a look at my code.
App.js
class App extends React.Component {
state = {
input: [],
};
addInput = (item) => {
let newInput = [...this.state.input, item];
//setState should be this way
this.setState({
input: newInput,
});
};
render() {
return (
<div className="App">
<h1>TO-DO LIST</h1>
{this.state.input.map((el) => (
<li> {el}</li>
))}
<SignInForm addInput={this.addInput} />
</div>
);
}
}
export default App;
Login file.
class SignInForm extends React.Component {
// constructor(props) {
// super(props);
state = {
temp: null,
};
// }
handleChange = (e) => {
e.preventDefault();
this.setState({
temp: e.target.value,
});
// this.props.addInput(e.target.value);
};
handleSubmit = (e) => {
e.preventDefault();
console.log(this.state.temp);
this.props.addInput(this.state.temp);
};
render() {
return (
<div className="container-form">
<form onSubmit={this.handleSubmit}>
<input
name="description"
type="text"
placeholder="add description"
onChange={this.handleChange}
value={this.state.input}
/>
<button type="submit">ADD</button>
</form>
</div>
);
}
}
export default SignInForm;
So I've been learning react but I'm having some trouble with forms.
I'm able to change a state after clicking a button in a form. However I've only been able to find resources that show me how to alert the new state.
What if I want to render the new state into the DOM?
I don't necessarily need the answer but would love to be shown the resources to figure out the answer myself to help me learn.
Here's what I've got:
import React from 'react';
import ReactDOM from 'react-dom';
class MyForm extends React.Component {
constructor(props) {
super(props);
this.state = { username: '',};
}
myChangeHandler = (e) => {
this.setState ({username: e.target.value});
}
mySubmitHandler = () => {
alert(this.state.username);
}
render() {
return (
<form>
<p>Enter your name, and submit:</p>
<input
type='text'
onChange={this.myChangeHandler}
/>
<button onClick={this.mySubmitHandler}>Submit</button>
</form>
);
}
}
ReactDOM.render(<MyForm />, document.getElementById('root'));
Make a state for display as the part of component state.
class MyForm extends React.Component {
constructor(props) {
super(props);
this.state = { userNameForInput: '', userNameForDisplay: ''}; // add 'userNameForDisplay'
}
myChangeHandler = (e) => {
this.setState ({ userNameForInput: e.target.value });
}
mySubmitHandler = () => {
this.setState ({ userNameForDisplay: this.state.userNameForInput }); // update `userNameForDisplay` by 'userNameForInput'
}
render() {
const { userNameForInput, userNameForDisplay } = this.state
return (
<form>
<p>Enter your name, and submit:</p>
<input
type='text'
onChange={this.myChangeHandler}
/>
<button onClick={this.mySubmitHandler}>Submit</button>
{/* render 'userNameForInput', 'userNameForDisplay' to DOM */}
{/* the format to render js variable in jsx is '{ jsVariable }' */}
<div>UserName From Input(update by input change): { userNameForInput }<div>
<div>UserName For Submit(update by submit button): { userNameForDisplay }<div>
</form>
);
}
}
I have a simple form on child component A. On submit I'm passing the data from the form to the parent component and storing the data in state.. I want to then move this data to a different child, child component B.(the sibling of A)
I'm having trouble getting the data to be rendered on submit in component B. I'm not sure how to trigger the rendering on submit or how to pass this information via props on submit.
Here is the Parent
class Msg extends React.Component {
constructor(props) {
super(props);
this.storeInput = this.storeInput.bind(this);
this.state = {
name: '',
msg: ''
};
}
storeInput (d) {
this.setState({
name: d.name,
msg: d.msg
})
}
render() {
return(
<div className='msgContainer'>
<Input
passBack={this.storeInput}/>
<Output />
</div>
)
}
}
Here is Component A
class Input extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.state = {
name: '',
msg: ''
};
}
handleChange(e) {
this.setState({[e.target.name]: e.target.value})
}
handleSubmit(e) {
e.preventDefault();
this.props.passBack(this.state);
}
render () {
const name = this.state.name;
const msg = this.state.msg;
return (
<div className='form-container'>
<form action="">
<label htmlFor="">name</label>
<input
name='name'
value={name}
onChange={this.handleChange}
type='text'></input>
<label htmlFor="">message</label>
<textarea
name='msg'
value={msg}
onChange={this.handleChange}
rows='5' cols='80'></textarea>
<input
onClick={this.handleSubmit}
type='submit'></input>
</form>
</div>
)
}
}
Here is Component B
class Output extends React.Component {
render () {
return(
<div className='output'>
</div>
)
}
}
Simply pass the state as props to Output like so:
Parent Component:
import React from 'react';
import Input from './Input';
import Output from './Output';
class Msg extends React.Component {
state = { name: '', msg: '' };
storeInput = d => {
this.setState({ name: d.name, msg: d.msg });
};
render() {
// destructure the state
const { name, msg } = this.state;
return (
<div className="msgContainer">
<Input passBack={this.storeInput} />
{/* pass the state as props to Output */}
<Output name={name} msg={msg} />
</div>
);
}
}
export default Msg;
Input.js
import React from 'react';
class Input extends React.Component {
state = { name: '', msg: '' };
handleChange = e => {
this.setState({ [e.target.name]: e.target.value });
};
handleSubmit = e => {
e.preventDefault();
this.props.passBack(this.state);
this.setState({ name: '', msg: '' }); // clear up the input after submit
};
render() {
const { name, msg } = this.state;
return (
<div className="form-container">
<form onSubmit={this.handleSubmit}>
<label htmlFor="">name</label>
<input
name="name"
value={name}
onChange={this.handleChange}
type="text"
/>
<label htmlFor="">message</label>
<textarea
name="msg"
value={msg}
onChange={this.handleChange}
rows="5"
cols="80"
/>
<input type="submit" />
</form>
</div>
);
}
}
export default Input;
Output.js
import React from 'react';
// destructure the props coming in from Msg
// no need for a class-based component
const Output = ({ name, msg }) => (
<div className="output">
<div>Output</div>
<p>{name}</p>
<p>{msg}</p>
</div>
);
export default Output;
Live demo: https://jsfiddle.net/c8th67zn/
I am using react-stripe-elements to create a token for payments. However, according to the documentation when the card form is wrapped in the Elements component it should automatically pickup which stripe elements to tokenize.
However, in this case we are presented with the error
You must provide a Stripe Element or a valid token type to create a Token.
Here is the code:
import React from 'react';
import {CardCVCElement, CardExpiryElement, CardNumberElement, PostalCodeElement, StripeProvider, Elements} from 'react-stripe-elements';
class CheckoutForm extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(ev) {
ev.preventDefault();
this.props.stripe.createToken({email: 'test#test.com'}).then(({token }) => {console.log('Received Stripe token:', token)});
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Card details
<CardNumberElement />
<CardExpiryElement />
<CardCVCElement />
<PostalCodeElement />
</label>
<button>Confirm order</button>
</form>
);
}
}
class App extends React.Component {
constructor() {
super();
this.state = { stripe: null };
}
componentDidMount() {
this.setState({ stripe: window.Stripe('test_key') });
}
render() {
return (
<StripeProvider stripe={this.state.stripe}>
<Elements>
<CheckoutForm stripe={this.state.stripe} />
</Elements>
</StripeProvider>
);
}
}
export default App;
According to the documentation the following should be true:
'Within the context of Elements, this call to createToken knows which Element to tokenize, since there's only one in this group.'
However, this doesn't seem to be the case. I have also tried using the single 'Card Element' and have not found any success in doing so.
It turns out I never managed to solve the issue using react-stripe-elements. I ended using the standard JS version (from the stripe documentation). Here is my current working solution:
import React from 'react';
class CheckoutForm extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
this.state = {
elements: null,
card: null
};
}
componentWillReceiveProps() {
this.setState({ elements: this.props.stripe.elements() }, () => {
this.setState({ card: this.state.elements.create('card') }, () => {
this.state.card.mount('#card-element');
});
});
}
handleSubmit(ev) {
ev.preventDefault();
this.props.stripe.createToken(this.state.card).then((token) => {
console.log('Received Stripe token:', token);
});
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<div className="row">
<label >
Credit or debit card
</label>
<div id="card-element"/>
<div id="card-errors" role="alert"/>
</div>
<button>Submit Payment</button>
</form>
);
}
}
class App extends React.Component {
constructor() {
super();
this.state = {stripe: window.Stripe('test_key')};
}
render() {
return (
<CheckoutForm stripe={this.state.stripe}/>
);
}
}
export default App;
In the comments they rightly say you need to use the HOC injectStripe.
The docs for stripe.createToken mention that you need to pass the element you wish to tokenize data from.
Also from the github repo README:
⚠️ NOTE injectStripe cannot be used on the same element that renders the Elements component; it must be used on the child component of Elements. injectStripe returns a wrapped component that needs to sit under but above any code where you'd like to access this.props.stripe.
In my specif case I was using a Mobx store and I needed to handle createToken and my form submission in the same place.
Even though I had a reference to stripe since initialisation it didn't work.
The createToken call needs to come from a component child of Elements and with stripe injected.
I ended up having:
#inject('signupStore')
#observer
class CardInput extends React.Component {
componentDidMount() {
const { signupStore } = this.props;
const handleCard = async name => {
return await this.props.stripe.createToken({ name: name });
};
signupStore.assignHandleCard(handleCard);
}
render() {
return (
<label>
Card details
<CardElement style={{ base: { fontSize: '18px' } }} />
</label>
);
}
}
export default injectStripe(CardInput);
Passing the handler back to the store, and then using it from there.
Part of signupStore:
#action
async submitForm(formValues) {
if (this.stripe && this.handleCard) {
const tokenResponse = await this.handleCard(
`${formValues.firstName} ${formValues.lastName}`
);
runInAction(() => {
console.log('Card token received ', tokenResponse);
if (tokenResponse) {
this.cardToken = tokenResponse.token.id;
formValues.cardToken = this.cardToken;
}
});
const response = await request.signup.submit(formValues);
return response;
}
return null;
}
With the new #stripe/react-stripe-js library it's a bit different. We need to use ElementsConsumer component. Load stripe using loadStripe method and use Elements component to use your form with Stripe.
Here is a basic example.
import { Elements, loadStripe } from "#stripe/react-stripe-js"
const stripePromise = loadStripe(STRIPEKEY)
<Elements stripe={stripePromise}>
<CardForm />
</Elements>
CardForm.js
import {
CardNumberElement,
CardExpiryElement,
CardCvcElement,
ElementsConsumer,
} from "#stripe/react-stripe-js"
const StripeForm = ({ stripe, elements }) => {
const handleSubmit = async () => {
if (!stripe || !elements) {
return
}
const cardNumberElement = elements.getElement(CardNumberElement)
const res = await stripe.createToken(cardNumberElement)
}
return (
<form>
<div>
<label htmlFor="cardNumber">Card Number</label>
<div>
<CardNumberElement />
</div>
</div>
<div>
<label htmlFor="cardName">Card Name</label>
<input
type="text"
name="cardName"
required
placeholder="Please Enter"
pattern="[A-Za-z]"
/>
</div>
<div>
<label htmlFor="expDate">Exp. Date</label>
<div>
<CardExpiryElement />
</div>
</div>
<div>
<label htmlFor="CVC">CVC</label>
<div>
<CardCvcElement />
</div>
</div>
</form>
)
}
const CardForm = () => {
return (
<ElementsConsumer>
{({ stripe, elements }) => (
<StripeForm stripe={stripe} elements={elements} />
)}
</ElementsConsumer>
)
}
export default CardForm
React js it's working for me
Card component , Get error , Card Detail and Generate Token
import React, { useState, useEffect } from "react";
import {loadStripe} from '#stripe/stripe-js';
import {CardElement,Elements,useStripe,useElements} from '#stripe/react-stripe-js';
const stripePromise = loadStripe('pk_test_YOUR_STRIPE_KYE');
const CheckoutForm = () => {
const stripe = useStripe();
const elements = useElements();
const handleSubmit = async (event) => {
event.preventDefault();
const {error, paymentMethod} = await stripe.createPaymentMethod({
type: 'card',
card: elements.getElement(CardElement),
});
console.log("paymentMethod",paymentMethod);
console.log("error", error);
if (paymentMethod) {
const cardElement = elements.getElement(CardElement);
let token = await stripe.createToken(cardElement);
console.log(token);
}
};
return (
<div>
<form onSubmit={ handleSubmit }>
<div className="login-box" id="step2" >
<div className="form-row">
<label for="card-element" style={ { color:" #76bbdf" } }>
Credit or debit card
</label>
</div>
<div >
<CardElement
className="StripeElement"
options={{
style: {
base: {
fontSize: '16px',
color: '#424770',
'::placeholder': {
color: '#aab7c4',
},
},
invalid: {
color: '#9e2146',
},
},
}}
/>
</div>
<button name="submintbtn2" className="btn btn-primary" > SUBSCRIBE </button>
</div>
</form>
</div>
)};
const Registration = () => (
<div>
<Elements stripe={stripePromise}>
<CheckoutForm />
</Elements>
</div>
);
export default Registration;