Only one element of type cardNumber can be created - node.js

I am trying to display my stripe component, but I am getting this error:
IntegrationError: Only one element of type cardNumber can be created.
I don't know why, since I'm only using it once in my entire app
Any ideas?
This is my index
import ReactDOM from 'react-dom';
import App from './App';
import * as serviceWorker from './serviceWorker';
import { loadStripe } from "#stripe/stripe-js";
import { Elements } from "#stripe/react-stripe-js";
import MyComponent from './components/StripeComponent';
const promise = loadStripe("xxx-xxx-xxx");
ReactDOM.render(
<React.StrictMode>
<Elements stripe={promise}>
<MyComponent/>
</Elements>
</React.StrictMode>,
document.getElementById('root')
);
And this is my component
import React from "react";
import {
useElements,
} from "#stripe/react-stripe-js";
const MyComponent: React.FC= (props)=>{
const elements = useElements();
const cardNumberElement = elements?.create('cardNumber', {
placeholder: ''
});
const cardExpiryElement = elements?.create('cardExpiry', {
placeholder: ''
});
const cardCvvElement = elements?.create('cardCvc', {
placeholder: ''
});
cardNumberElement?.mount('#card-number-element')
cardExpiryElement?.mount('#card-expiry-element')
cardCvvElement?.mount('#card-cvv-element')
const handleSubmit = async (ev: any) => {
ev.preventDefault();
};
return (
<form id="payment-form" onSubmit={handleSubmit}>
<div id="card-number-element"></div>
<div id="card-expiry-element"></div>
<div id="card-cvv-element"></div>
</form>
);
}
export default MyComponent

Seems it is because you create and mount the card components in the functional component body they are executed on every render of the component, i.e. as an inadvertent side-effect.
Place the creation and mounting logic in an useEffect hook with an empty dependency array so that it is invoked only once when the component mounts.
import React, { useEffect } from "react";
import { useElements } from "#stripe/react-stripe-js";
const MyComponent: React.FC = (props) => {
const elements = useElements();
// Effect hook to run once on component mount
useEffect(() => {
const cardNumberElement = elements?.create("cardNumber", {
placeholder: ""
});
const cardExpiryElement = elements?.create("cardExpiry", {
placeholder: ""
});
const cardCvvElement = elements?.create("cardCvc", {
placeholder: ""
});
cardNumberElement?.mount("#card-number-element");
cardExpiryElement?.mount("#card-expiry-element");
cardCvvElement?.mount("#card-cvv-element");
}, []); // <-- empty dependency array
const handleSubmit = async (ev: any) => {
ev.preventDefault();
};
return (
<form id="payment-form" onSubmit={handleSubmit}>
<div id="card-number-element"></div>
<div id="card-expiry-element"></div>
<div id="card-cvv-element"></div>
</form>
);
};

useEffect(() => {
if (elements) {
const cardNumberElement =
elements.getElement("cardNumber") || // check if we already created element
elements.create("cardNumber", defaultInputStyles); // create if dont
cardNumberElement.mount("#numberInput");
}
}, [elements]);

I had the same problem, in my case, I had a reference to CardNumberElement in another section of my code. After removing it, everything worked fine.

Related

Trouble with dividing an API into multiple components instead of just one

I'm having trouble for the past few days in this problem.
Explanation of the problem:
I'm using Axios in order to get data inside of state (Pokémon's), But, everything is rendering inside one component (creating an array and list and shows the list) , while I need every Pokémon I get from the API to be inside his own component (so that I can images per Pokémon and etc.)
Does anybody perhaps knows how to do so? If u do, please answer and explain to me (And if it wont be any trouble, modify the code), Thanks in advance, Mikey. (Using react-ts, node.js and axios)
import React, { useState, useEffect } from 'react';
import axios from 'axios';
export default function PokeCont() {
const [pokemons, setPokemons] = useState<any>();
const onClick = () => {
axios.get('https://pokeapi.co/api/v2/pokemon?limit=6').then((response) => {
setPokemons(response.data.results);
});
};
useEffect(() => {
onClick();
}, []);
return (
<div>
{pokemons &&
pokemons.map((pokemon: any) => (
<div key={pokemon.name}>
<p>{pokemon.name}</p>
</div>
))}
</div>
);
}
Here is an example ;)
import { useState, useEffect } from "react";
import axios from "axios";
export default function App() {
return (
<div className="App">
<PokemonContainer />
</div>
);
}
function PokemonContainer() {
const [pokemons, setPokemons] = useState<any[]>([]);
const onClick = () => {
axios.get("https://pokeapi.co/api/v2/pokemon?limit=6").then((response) => {
setPokemons(response.data.results);
});
};
useEffect(() => {
onClick();
}, []);
return (
<div>
{pokemons &&
pokemons.map((pokemon) => (
<PokemonItem key={pokemon.name} info={pokemon} />
))}
</div>
);
}
function PokemonItem({ info }) {
return (
<div>
<h2>{info.name}</h2>
<img src={info.image} width="100" height="100" alt=""></img>
</div>
);
}
Add necessary changes to components like export default and types.
import React, { useState, useEffect } from 'react'
import axios from 'axios'
***Component 1: Pokemon***
Pokemon = props => {
return (
<>
<div key={props.name}>
<p>{props.name}</p>
</div>
</>
)
}
***Component 2: Parent Pokemon which renders your Pokemon as Component ***
export default function PokeClass() {
const [pokemons, setPokemons] = useState()
const onClick = () => {
axios.get("https://pokeapi.co/api/v2/pokemon?limit=6").then((response) => {
setPokemons(response.data.results)
})
}
useEffect(() => {
onClick()
}, []);
return (
<>
{pokemons.map((item => {
return <Pokemon name={item.name} />
}))}
</>
)
}

I am trying to display data from an external API, how can I fix the issue in my code?

This is the error message I am getting
TypeError: undefined is not an object (evaluating 'drinkList.drinks[0]')
How can I fix the error so that I can use the app to fetch data from the external api?
This is my drink.js code:
import React, { useEffect, useState } from "react";
import axios from "axios";
import Drinks from "./Drinks";
function Home() {
const [drinkName, setDrinkName]= useState([]);
const [drinkList, setDrinkList] = useState([]);
const drinksURL = `https://www.thecocktaildb.com/api/json/v1/1/search.php?s=${drinkName}`;
const handleChangeDrink= e => {
setDrinkName(e.target.value);
}
const getDrink = () => {
axios
.get(drinksURL)
.then(function (response) {
setDrinkList(response.data);
console.log(drinksURL);
})
.catch(function (error) {
console.warn(error);
});
};
return (
<main className="App">
<section className="drinks-section">
<input
type="text"
placeholder="Name of drink (e.g. margarita)"
onChange={handleChangeDrink}
/>
<button onClick={getDrink}>Get a Drink Recipe</button>
<Drinks drinkList={drinkList} />
</section>
</main>
);
}
export default Home;
This is my Drink.js code:
import React from "react";
function Drinks({ drinkList }) {
if (!drinkList) return <></>;
return (
<section className="drinkCard">
<h1>{drinkList.drinks[0].strDrink}</h1>
</section>
);
}
export default Drinks;
Couple of problems here...
drinkName is initialised as an array but it appears to be expecting a string
drinkList is initialised as an array but the data from the API is an object. You may want to assign the drinks array from the response instead
drinksUrl is never updated
An empty array is still truthy
Some easy fixes
const [drinkName, setDrinkName]= useState(null) // initialise as null
const [drinkList, setDrinkList] = useState([])
// don't include the "s" parameter here
const drinksURL = "https://www.thecocktaildb.com/api/json/v1/1/search.php"
const getDrink = () => {
// pass drinkName as a param
axios.get(drinksURL, {
params: { s: drinkName }
}).then(res => {
// note that we're extracting `drinks`
setDrinkList(res.data.drinks)
}).catch(console.warn)
}
and in Drink.js
function Drinks({ drinkList }) {
// check the array length
return drinkList.length && (
<section className="drinkCard">
<h1>{drinkList[0].strDrink}</h1>
</section>
)
}

How to get the links in Draft js in read only mode?

I am creating a simple blog writing application. I am using Draft.js as an editor. I am able to create the link while writing the blog but when I go into read mode all the links are missing. Here are the React code for writing and reading the blogs. For simplicity I am storing the editorState/data in localStorage. Here is WriteBlog.js file
import React, { Component } from "react";
import Editor, { createEditorStateWithText } from "draft-js-plugins-editor";
import createInlineToolbarPlugin from "draft-js-inline-toolbar-plugin";
import createLinkPlugin from "draft-js-anchor-plugin";
import createToolbarPlugin, { Separator } from "draft-js-static-toolbar-plugin";
import {
convertFromRaw,
EditorState,
RichUtils,
AtomicBlockUtils,
convertToRaw
} from "draft-js";
import { ItalicButton, BoldButton, UnderlineButton } from "draft-js-buttons";
import editorStyles from "./editorStyles.css";
import buttonStyles from "./buttonStyles.css";
import toolbarStyles from "./toolbarStyles.css";
import linkStyles from "./linkStyles.css";
import "draft-js-alignment-plugin/lib/plugin.css";
const staticToolbarPlugin = createToolbarPlugin();
const linkPlugin = createLinkPlugin({
theme: linkStyles,
placeholder: "http://…"
});
const inlineToolbarPlugin = createInlineToolbarPlugin({
theme: { buttonStyles, toolbarStyles }
});
const { Toolbar } = staticToolbarPlugin;
const { InlineToolbar } = inlineToolbarPlugin;
const plugins = [staticToolbarPlugin, linkPlugin];
const text =
"Try selecting a part of this text and click on the link button in the toolbar that appears …";
export default class WriteBlog extends Component {
state = {
editorState: createEditorStateWithText(text)
};
onChange = editorState => {
let contentRaw = convertToRaw(this.state.editorState.getCurrentContent());
const stringyfyRawContent = JSON.stringify(contentRaw);
localStorage.setItem("blogcontent", JSON.stringify(contentRaw));
this.setState({
editorState
});
};
handleSave = async e => {
e.preventDefault();
// await this.setState({
// saveblog: 1,
// publish: 0
// });
// this.props.create_post(this.state);
// console.log("save state", this.state);
localStorage.setItem(
"blogsaveblog",
JSON.stringify(this.state.editorState)
);
};
focus = () => this.editor.focus();
render() {
return (
<div className={editorStyles.editor} onClick={this.focus}>
<form onSubmit={this.handleSave}>
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
plugins={plugins}
ref={element => {
this.editor = element;
}}
/>
<Toolbar>
{// may be use React.Fragment instead of div to improve perfomance after React 16
externalProps => (
<div>
<BoldButton {...externalProps} />
<ItalicButton {...externalProps} />
<UnderlineButton {...externalProps} />
<linkPlugin.LinkButton {...externalProps} />
</div>
)}
</Toolbar>
<button
type="submit"
className="btn btn-primary"
style={{ margin: "10px" }}
>
Save
</button>
</form>
</div>
);
}
}
and here is ReadBlog.js file
import React, { Component } from "react";
import Editor, { createEditorStateWithText } from "draft-js-plugins-editor";
import createInlineToolbarPlugin from "draft-js-inline-toolbar-plugin";
import createLinkPlugin from "draft-js-anchor-plugin";
import createToolbarPlugin, { Separator } from "draft-js-static-toolbar-plugin";
import { convertFromRaw, EditorState, convertToRaw } from "draft-js";
import { ItalicButton, BoldButton, UnderlineButton } from "draft-js-buttons";
import editorStyles from "./editorStyles.css";
import buttonStyles from "./buttonStyles.css";
import toolbarStyles from "./toolbarStyles.css";
import linkStyles from "./linkStyles.css";
import "draft-js-alignment-plugin/lib/plugin.css";
const staticToolbarPlugin = createToolbarPlugin();
const linkPlugin = createLinkPlugin({
theme: linkStyles,
placeholder: "http://…"
});
const inlineToolbarPlugin = createInlineToolbarPlugin({
theme: { buttonStyles, toolbarStyles }
});
const { Toolbar } = staticToolbarPlugin;
const { InlineToolbar } = inlineToolbarPlugin;
const plugins = [staticToolbarPlugin, linkPlugin];
const text =
"Try selecting a part of this text and click on the link button in the toolbar that appears …";
export default class ReadBlog extends Component {
state = {
editorState: createEditorStateWithText(text)
};
componentDidMount = () => {
const rawContentFromdb = convertFromRaw(
JSON.parse(localStorage.getItem("blogcontent"))
);
const initialEditorStatedb = EditorState.createWithContent(
rawContentFromdb
);
this.setState({ editorState: initialEditorStatedb });
};
focus = () => this.editor.focus();
render() {
return (
<div className={editorStyles.editor} onClick={this.focus}>
<Editor
editorState={this.state.editorState}
plugins={plugins}
readOnly={true}
ref={element => {
this.editor = element;
}}
/>
</div>
);
}
}
I know this is super late, but you are not adding the decorator which is why this is not working. In this case, you'll want to use compositeDecorator to build your decorator object, and initialize the react state with it.
const decorator = new CompositeDecorator([
{
strategy: linkStrategy,
component: LinkDecorator,
},
]);
const [editorState, setEditorState] = useState(() =>
EditorState.createWithContent(initialContentState, decorator),
);

pass state as props in component child in React

I get data from a local server, catch them with axios.get, and save them in my state. It's ok, but when i want to pass it as props in an component child, KABOOM! Doesn't work.
I'm looking for a solution, I think it's lyfecycle problem but i'm not sure.
App.js
import React, { Component } from 'react';
import './style/App.css';
import axios from 'axios'
import Table from './Components/Table'
class App extends Component {
state = {
tabData: [],
}
componentWillMount = () => {
this.getDataFromServer()
}
getDataFromServer = () => {
axios.get("http://localhost:8000")
.then((response) => {
const twentyObj = response.data.splice(-20);
this.setState({
tabData:twentyObj
})
console.log(this.state.tabData)
})
.catch(function (error) {
console.log(error);
})
}
render() {
return (
<div className="App">
<Table stateData={this.state.tabData}/>
</div>
);
}
}
export default App;
Developer Tools Browser say:
TypeError: _this.props is undefined
(for this.props.tabData.map in Table.js)
Table.js
import React from 'react';
import Cell from './Cell'
const Table = (props) => {
return(
<div>
{this.props.tabData.map( item =>
<Cell key={item.index}
time={item.timestamp}
nasdaq={item.stocks.NASDAQ}
cac40={item.stocks.CAC40}/>
)}
</div>
)
}
export default Table;
Table is functional component this has no value there and thats what the error message is telling you.
You should use props.tabData and not this.props.tabData
UPDATE:
Here you are passing it as stateData and not tabData Try props.stateData

Losing currentUser when App component refreshes?

I am currently working on a simple web app using React, Node.js, passport-google-oauth20.
For some reason, whenever the application re-mounts, I lose the currentUser state. It's as if req.user is just lost.
The way it works is I first fetch the current user when the application mounts and set this.state.currentUser to the results. The issue is when the page refreshes. The component re-mounts and I lose the user. I tried logging the user and receive null.
Hopefully I explained this well enough... here is the code:
App component:
import React from 'react';
import List from './List';
import ListForm from './ListForm';
import * as helpers from '../helpers';
class App extends React.Component{
state = {
currentUser: '',
}
componentDidMount() {
helpers.fetchUser()
.then(data => {
this.setState({
currentUser: data
});
});
}
onSubmit = (id, item) => {
helpers.addItem(id, item);
}
render() {
return (
<div className="container">
<List
currentUser={this.state.currentUser}
onSubmit={this.onSubmit}
/>
</div>
);
}
};
export default App;
Helpers:
import axios from 'axios';
export const fetchUser = async () => {
const resp = await axios.get('/api/current_user');
return resp.data;
}
export const addItem = (id, newItem) => {
axios.post("/api/" + id + "/addItem", newItem);
}

Resources