The moment i try to enter in the search box its leading to the typeerror. I have declared the searchResults as a state. but its still throwing an error. Am i not calling the state properly? What should i change? is it the map method that i'm writing it ?
Sorry i'm new to react could someone possibly tell what i'm doing wrong thanks.
Search.js
import React, { Component } from 'react';
import './Search.css';
import axios from 'axios';
class Search extends Component {
constructor(props){
super(props);
this.state = {
searchResults : []
}
}
componentDidMount () {
const token = 'Bearer Wookie2019';
axios.get('https://wookie.codesubmit.io/movies?q=<search_term>',{
headers: {
'Authorization': token
}
}).then(response => {
this.setState({movies : response.data.movies});
console.log(response);
});
}
searchHandler = (event) => {
this.setState({
searchResults : event.target.value
})
console.log(this.searchResults);
}
render(){
return (
// <div className="search" >
// <input className = "form-control" type="text" avlue="inputVal" onChange = {this.searchHandler}/>
// {/* <i className="fas fa-search"></i> */}
// <button className ="btn btn-info">Search</button>
// <div className ="searchres">
// </div>
// </div>
<div>
<form>
<input className = "form-control" placeholder = "Search Movies" ref = { input => this.search = input} onChange = {this.searchHandler}/>
</form>
<div className = "searchresults">
{ this.state.searchResults.map(searchResult => <searchResult movie={this.state.searchResults}>{searchResult.title}</searchResult>)}
</div>
</div>
)
}
}
export default Search;
Title.js
import React, { Fragment } from 'react';
import Search from '../Search/Search';
import './Title.css';
const Title = (props) => {
return (
<Fragment>
<div className ="conatiner">
<div className ="row titlehead">
<div className="col-6">
<h3 className = "title">WOOKIE <br/> MOVIES</h3>
</div>
<div className = "col-6 searchMovie">
<Search {...props} />
</div>
</div>
</div>
</Fragment>
)
}
export default Title
Issues
If I had to guess I would say your onChange handler is setting your state to be undefined, or rather, to whatever you are inputting, which is a string, not an array.
Another issue is that you attempt to fetch your data when the component mounts, not when a search is entered.
The search is never invoked after mounting.
Solution
I suggest using the form's onSubmit event to do the search. Provide the input with an id attribute that can be accessed from the onSubmit event object. Pass the entered value to a computed query string.
import React, { Component } from 'react';
import './Search.css';
import axios from 'axios';
class Search extends Component {
constructor(props){
super(props);
this.state = {
searchResults : []
}
}
searchHandler = (event) => {
event.preventDefault();
const searchTerm = event.target.searchTerm.value
const token = 'Bearer Wookie2019';
axios.get(`https://wookie.codesubmit.io/movies?q=${searchTerm}`,{
headers: {
'Authorization': token
}
}).then(response => {
this.setState({ movies: response.data.movies });
console.log(response);
});
};
render(){
return (
<div>
<form onSubmit={searchHandler}>
<input
id="searchTerm"
className="form-control"
placeholder="Search Movies"
/>
<button type="submit">Search</button>
</form>
<div className="searchresults">
{this.state.searchResults.map(searchResult => <searchResult movie={this.state.searchResults}>{searchResult.title}</searchResult>)}
</div>
</div>
)
}
}
I want to take data from an input field and pass it into a to Generate QR code. When I pass the value as a text its work. But can’t pass the input value. Does anyone have a simple example of this working?
import React, {Component} from 'react'
import QrCode from 'react.qrcode.generator'
class DemoEdit extends Component {
constructor() {
super();
this.state = {
topicIn: "",
topicOut:""
};
this.handleChange=this.handleChange.bind(this);
this.generate=this.generate.bind(this);
}
handleChange ({ target}){
this.setState({
[target.name] : target.value
})
}
generate(){
this.setState({
topicOut:this.state.topicIn
})
}
render() {
return <div>
<input
type="text"
name="topicIn"
placeholder="Enter Text Here..."
value={this.state.topicIn}
onChange={this.handleChange}
/>
<button value="Send" onClick={this.generate}>Generate</button>
<p>{this.state.topicOut}</p>
<QrCode value={this.state.topicOut}/>
</div>
}
}
export default DemoEdit;
Use a different package. I just tried qrcode.react
import React, { Component } from "react";
import QrCode from "qrcode.react";
class DemoEdit extends Component {
constructor() {
super();
this.state = {
topicIn: ""
};
this.handleChange = this.handleChange.bind(this);
}
handleChange({ target }) {
console.log("value", target.value);
this.setState({
topicIn: `${target.value}`
});
}
render() {
return (
<div>
<input
type="text"
name="topicIn"
placeholder="Enter Text Here..."
value={this.state.topicIn}
onChange={this.handleChange}
/>
<QrCode value={this.state.topicIn} />
</div>
);
}
}
export default DemoEdit;
or as a more fancy functional component with hooks, which I totally recommend to use
import React, { useState } from "react";
import QrCode from "qrcode.react";
const DemoEdit = () => {
const [topicIn, setTopicIn] = useState("");
const onChange = (event) => setTopicIn(event.target.value);
return (
<div>
<input
type="text"
name="topicIn"
placeholder="Enter Text Here..."
value={topicIn}
onChange={onChange}
/>
<QrCode value={topicIn} />
</div>
);
};
export default DemoEdit;
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;
I am new to react and having hard time figuring on how to show up the value from another component to the edit file component. Basically, I am able to create a message using draft.js rich text editor and able to save it to the database in the backend. Now I need to work on the update/edit part. How do I get the description state value to show up in the rich text editor? Can anyone please help?
Create File
import { EditorState } from 'draft-js';
class CreateModal extends Component {
constructor(props) {
super(props);
this.state = {
description: EditorState.createEmpty()
};
this.handleEditorState = this.handleEditorState.bind(this);
}
handleEditorState(editorState) {
this.setState({
description: editorState
})
}
render() {
const { release } = this.props.state;
return (
<div>
...
<CreateForm
description={this.state.description}
handleEditorState={this.handleEditorState}
handleSubmit={(e) => handleSubmit(e)}
/>
...
);
}
}
Form file
import { Editor } from 'react-draft-wysiwyg';
import '../../react-draft-wysiwyg.css';
class CreateForm extends Component {
render() {
const { description, handleEditorState, handleSubmit } = this.props;
return (
<div>
<form className="form-horizontal" onSubmit={handleSubmit}>
<Editor
editorState={description}
onEditorStateChange={handleEditorState}
/>
{/* Buttons */}
<div className={`modal-footer ${styles.modalFooter}`}>
...
</div>
</form>
</div>
);
}
}
Edit file
class EditAccessInstructionModal extends Component {
constructor(props) {
super(props);
this.state = {
description: EditorState.createEmpty()
}
}
componentWillMount(){
this.setState({
description: this.props.accessInstructions.description
});
}
componentWillReceiveProps(nextProps) {
this.setState({
description: nextProps.accessInstructions.description
});
}
onDescriptionChange(event) { this.setState({ description: event.target.value }); }
render() {
const { description } = this.state;
return (
<div className="btn-group">
<div className={`modal-body ${styles['proj-modal-body']}`}>
<form id="modalForm" className="form-horizontal">
<Editor
value={description}
/>
</form>
</div>
</div>
)
}
}
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;