Stripe : Could not find Elements context error in nextjs - reactjs

I am using stripe following package in nextjs 12
import { loadStripe } from "#stripe/stripe-js";
import { Elements } from "#stripe/react-stripe-js";
It is working well in developement mode but while production build it is throwing this error
Error: Could not find Elements context; You need to wrap the part of your app that calls useStripe() in an <Elements> provider.
I am using Elements as a parent container and Checkoutform inside Elements as a child
import React from 'react'
import { useAppContext } from '#/context/AppContext';
import { loadStripe } from "#stripe/stripe-js";
import { Elements } from "#stripe/react-stripe-js";
import Checkoutform from './Checkoutform';
import AppLoader from '#/components/common/Loader';
const Payment = () => {
const { state } = useAppContext();
const { user, planType } = state;
const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_KEY);
const options = {
clientSecret: planType.orderData.client_secret,
appearance: {
theme: 'stripe',
}
};
return (
options.clientSecret && options.clientSecret.length > 0 ? (
<Elements stripe={stripePromise} options={options} >
<Checkoutform userData={user} planType={planType} />
</Elements >
) : (
<AppLoader />
)
)
}
export default Payment
Checkoutform.js
import React, { useEffect, useState } from "react";
import {
PaymentElement,
useStripe,
useElements
} from "#stripe/react-stripe-js";
import AppLoader from "#/components/common/Loader";
import { toast } from "react-toastify";
import { baseURL } from "#/constants/utils/universal";
export default function Checkoutform(props) {
const { userData, planType } = props;
const stripe = useStripe();
const elements = useElements();
const [message, setMessage] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const [isInitialized, setIsInitialized] = useState(true);
const redirectUrl = baseURL + "/pricing/payment/success";
useEffect(() => {
if (typeof window === "undefined" && !stripe) {
return;
}
const clientSecret = new URLSearchParams(window.location.search).get(
"payment_intent_client_secret"
);
if (!clientSecret) {
return;
}
stripe.retrievePaymentIntent(clientSecret).then(({ paymentIntent }) => {
switch (paymentIntent.status) {
case "succeeded":
toast.success("Thankyou!, Payment Successful, please check your email for your receipt");
setMessage("Payment succeeded!");
break;
case "processing":
setMessage("Your payment is processing.");
break;
case "requires_payment_method":
setMessage("Your payment was not successful, please try again.");
break;
default:
setMessage("Something went wrong.");
break;
}
});
}, [stripe]);
useEffect(() => {
setTimeout(() => {
if (typeof window !== "undefined") {
setIsInitialized(false);
}
}, 1000);
}, [])
const handleSubmit = async (e) => {
e.preventDefault();
if (!stripe || !elements) {
return;
}
setIsLoading(true);
const { error } = await stripe.confirmPayment({
elements,
confirmParams: {
return_url: redirectUrl,
},
});
if (error.type === "card_error" || error.type === "validation_error") {
toast.error("Oops! some error occurred, please try again");
setMessage(error.message);
} else {
toast.error("Oops! some error occurred, please try again");
setMessage("An unexpected error occured.");
}
setIsLoading(false);
};
return (
<div className='container my-5 pt-5'>
<div className='row'>
<div className='col-md-6 col-12 mx-auto'>
<div className='card shadow-sm p-5'>
{
!isInitialized ?
<form id="payment-form" onSubmit={handleSubmit}>
<PaymentElement id="payment-element" className="mb-5" />
<div className="mt-3 d-grid">
<button disabled={isLoading || !stripe || !elements} id="submit" className="btn app-cta">
<span id="button-text">
{isLoading ? "processing please wait..." : "Pay now"}
</span>
</button>
</div>
{/* Show any error or success messages */}
{message && <div id="payment-message" className='my-2 small fw-light text-danger'>{message}</div>}
</form>
:
<AppLoader />
}
</div>
</div>
</div>
</div>
);
}
please help me what i am doing wrong or what i have to add for production build

Jonathan Steele is right if you are using checkoutform.js as a component then make sure you kept it inside components folder which should be outside pages folder. Because if it is inside pages folder then during build nextjs will trying to pre-render it by considering it as a page which will give you this error

Related

How to use useSearchParams Hook with React Router v6

I am trying to implement a search parameter functionality to my React image search app. And, I have learned that I need to (can) use the useSearchParams Hook, but I am not sure how to make these changes.
So, basically I want the URL to be something like localhost:3000/input&page=1, meaning that whatever comes after the slash is going to be the input value and key/value pair for page numbers.
As you can see in the app.js, I have these 3 main Routes and the Home Route (renders Main.js) is the one I am mainly working on. Also, Main.js renders Header.js (renders form and others).
I am thinking that I should create a new Route in the app.js but I am not sure what to do.
import './App.css';
import Home from './components/pages/Home';
import Favorites from './components/pages/Favorites';
import Error from './components/pages/Error';
import { BrowserRouter, Routes, Route } from 'react-router-dom'
import { SkeletonTheme } from 'react-loading-skeleton';
import { useDarkMode } from './components/Navbar';
function App() {
const darkMode = useDarkMode(state => state.darkMode)
let style
if (darkMode === 'light') {
style = 'wrapper'
} else {
style = 'wrapper-dark'
}
return (
<div className={style}>
<SkeletonTheme baseColor="#808080" highlightColor="#b1b1b1">
<BrowserRouter>
<Routes>
<Route path='/' element={<Home />} />
<Route path='favorites' element={<Favorites />} />
<Route path='*' element={<Error />} />
</Routes>
</BrowserRouter>
</SkeletonTheme>
</div>
);
}
export default App;
import React from 'react'
import Header from './Header'
import Image from './Image'
import { useState, useEffect, useRef } from 'react'
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome'
import { faTriangleExclamation } from '#fortawesome/free-solid-svg-icons'
// import InfiniteScroll from 'react-infinite-scroll-component'
function Main() {
const [input, setInput] = useState('')
const [allImages, setAllImages] = useState([])
// const [totalResults, setTotalResults] = useState(null)
const [isVisible, setIsVisible] = useState(false)
const [error, setError] = useState(null)
const [showError, setShowError] = useState(false)
const [fadeOut, setFadeOut] = useState(false)
const [page, setPage] = useState(1)
const paginationRef = useRef(false)
// get
useEffect(() => {
if (localStorage.getItem('input')) {
setInput(JSON.parse(localStorage.getItem('input')))
}
if (localStorage.getItem('allImages')) {
setAllImages(JSON.parse(localStorage.getItem('allImages')))
// setTotalResults(JSON.parse(localStorage.getItem('totalResults')))
setIsVisible(JSON.parse(localStorage.getItem('isVisible')))
setPage(JSON.parse(localStorage.getItem('page')))
paginationRef.current = true
}
}, [])
// set
//* dryer?
useEffect(() => {
localStorage.setItem('input', JSON.stringify(input))
}, [input])
useEffect(() => {
localStorage.setItem('allImages', JSON.stringify(allImages))
}, [allImages])
// useEffect(() => {
// localStorage.setItem('totalResults', JSON.stringify(totalResults))
// }, [totalResults])
useEffect(() => {
localStorage.setItem('isVisible', JSON.stringify(isVisible))
}, [isVisible])
function handleChange(event) {
setInput(event.target.value)
}
// display nothing by default
// display image-list when user press search button
// function handleSubmit(event) {
// event.preventDefault()
// // interpolate input state and .env variable to API
// fetch(`https://api.unsplash.com/search/photos?query=${input}&client_id=${process.env.REACT_APP_UNSPLASH_API_KEY}`)
// .then(res => res.json())
// .then(data => setAllImages(data.results))
// }
async function fetchImages() {
try {
const res = await fetch(`https://api.unsplash.com/search/photos?&page=${page}&per_page=30&query=${input}&client_id=${process.env.REACT_APP_UNSPLASH_API_KEY}`)
const data = await res.json()
if (data.total !== 0) {
setAllImages(data.results)
// setTotalResults(data.total)
setIsVisible(true)
}
} catch(error) {
setError(error)
}
}
const handleSubmit = async (event) => {
event.preventDefault();
fetchImages()
setPage(1)
paginationRef.current = true
}
// error
useEffect(() => {
if (error) {
setShowError(true)
setTimeout(() => {
setFadeOut(true)
setTimeout(() => {
setShowError(false)
}, 1000)
}, 5000)
}
}, [error])
// total results
// let results
// if (totalResults >= 10000) {
// results = 'Total Results: ' + totalResults + '+'
// } else if (totalResults > 0) {
// results = 'Total Results: ' + totalResults
// } else if (totalResults === 0) {
// results = 'Nothing Found'
// }
// pagination
useEffect(() => {
if (paginationRef.current) {
fetchImages()
}
localStorage.setItem('page', JSON.stringify(page))
}, [page])
function handlePrev() {
setPage(prevState => prevState - 1)
fetchImages()
}
function handleNext() {
setPage(prevState => prevState + 1)
fetchImages()
}
return (
<main>
<Header
input={input}
handleChange={handleChange}
handleSubmit={handleSubmit}
/>
{showError && <div className={`network-error ${fadeOut ? 'fade-out' : ''}`}>
<i><FontAwesomeIcon icon={faTriangleExclamation} /></i>
<div className='network-error--message'>
<h5>Network Error</h5>
<p>Please check your Internet connection and try again</p>
</div>
</div>}
{/* <p className='main--results'>{results}</p> */}
<div className='main--image-list mt-5 pb-5'>
{allImages.map(el => (
<Image
key={el.id}
// do need spread operator below for img's src to work in Image.js
{...el}
el={el}
/>
))}
</div>
{isVisible && <div className='main--pagination'>
<button disabled={page === 1} onClick={handlePrev}>
Prev
</button>
<h5 className='main--pagination--h5'>{page}</h5>
<button onClick={handleNext}>
Next
</button>
</div>}
</main>
)
}
export default Main
import React from 'react'
import Navbar from './Navbar'
function Header(props) {
return (
<div className='header'>
<Navbar />
<h2 className='header--heading text-center text-light'>Find Images</h2>
<div className='header--form'>
<form onSubmit={props.handleSubmit}>
<input
className='header--form--input'
autoComplete='off'
type='text'
placeholder='Search'
onChange={props.handleChange}
name='input'
value={props.input}
/>
</form>
</div>
</div>
)
}
export default Header
If you are just wanting to initialize the page state to the page queryParam the the following could work. If uses the useSearchParams to access the queryString and return a constructed URLSearchParams object which can then access individual query params. Pass the "page" query param as the initial page state value.
const [searchParams] = useSearchParams();
const [page, setPage] = useState(Number(searchParams.get("page")) || 1);
In all likelihood though you'll not want competing "sources of truth" for what the current page is. If you want the URL queryString to be the source of truth then remove the page state and just read/update the "page` query parameter directly.
Example:
function Main() {
const [searchParams, setSearchParams] = useSearchParams();
...
const page = Number(searchParams.get("page"));
// get
useEffect(() => {
...
if (localStorage.getItem('allImages')) {
...
setSearchParams(params => {
params.set("page", JSON.parse(localStorage.getItem('page')) || 1);
return params;
});
...
}
}, []);
...
const handleSubmit = async (event) => {
event.preventDefault();
...
setSearchParams(params => {
params.set("page", 1);
return params;
});
...
}
...
// pagination
useEffect(() => {
if (paginationRef.current) {
fetchImages();
}
localStorage.setItem('page', JSON.stringify(page));
}, [page])
function handlePrev() {
setSearchParams(params => {
params.set("page", Math.max(1, page - 1));
return params;
});
...
}
function handleNext() {
setSearchParams(params => {
params.set("page", page + 1);
return params;
});
...
}
return (
...
);
}

SearchBar Assistance-React

So I am trying to set a searchbar that has a drop down menu that gives you options on what you want to search for=and then let the user input. I have a list of inspections that I want to base that on.
For example I want to search inspections that only have issues with pests, so the user selects the pest option for search and then inputs-hive beetles
so the dropdown should have an option of searching by: pests, notes, actions taken, and so forth, my table has 8 values that I want to specific each search.
I have am using React for this and my database is in django, any suggestions on how to tackle this? The research I found is not really helpful.
My InpsectionSearch
import {React, useState} from "react";
const SearchInspections = (inspections) => {
const [searchField, setSearchField] = useState("")
const [searchResults, setSearchResults] = useState([])
function handleChange(event){
event.preventDefault()
const filteredInspections = inspections.filter((inspections) => {
return (
inspections.eggs().includes(searchField.toLowerCase()) ||
inspections.larvae().includes(searchField.toLowerCase()) ||
inspections.sealed_brood().includes(searchField.toLowerCase()) ||
inspections.covered_bees().includes(searchField.toLowerCase()) ||
inspections.nectar_honey().includes(searchField.toLowerCase()) ||
inspections.pollen().includes(searchField.toLowerCase()) ||
inspections.pest_spotted.toLowerCase().includes(searchField.toLowerCase()) ||
inspections.pest_action.toLowerCase().includes(searchField.toLowerCase()) ||
inspections.notes_concerns.toLowerCase().includes(searchField.toLowerCase())
)
})
setSearchResults(filteredInspections)
if(searchField.length > 0){
inspections(searchResults)
}
}
return (
<form onSubmit={handleChange}>
<h3>Search For Your Item</h3>
<input type="search" placeholder='Search Song' value={searchField} onChange={event => setSearchField(event.target.value)}/>
<button type='submit'>Click twice to search</button>
</form>
);
}
export default SearchInspections;
my Inspection Page where the searchbar will be
import { React, useState, useEffect } from "react";
import { useParams } from "react-router-dom";
import axios from "axios";
import useAuth from "../../hooks/useAuth";
import DisplayInspections from "../../components/DisplayInspections/DisplayInspections";
import InspectionTracker from "../../components/InspectionTracker/InspectionTracker";
import SearchInspections from "../../components/InspectionSearch/InspectionSearch"
const InspectionPage = (props) => {
const [user, token] = useAuth();
const [inspections, setInspections] = useState([]);
const { id } = useParams();
useEffect(() => {
fetchInspections();
}, [token]);
const fetchInspections = async () => {
try {
let response = await axios.get(
`http://127.0.0.1:8000/api/inspections/all/${id}`,
{
headers: {
Authorization: "Bearer " + token,
},
}
);
setInspections(response.data);
} catch (error) {
console.log(error.response.data);
}
};
function applyFilter(category, userInput){
if(category === 'All' || userInput ===''){
console.log('working!')
fetchInspections();
}
else
{
let newInspections = inspections.filter(function(element){
if(element[category] === userInput){
return true;
}
})
setInspections(newInspections);
}
}
return (
<div className="container">
<InspectionTracker inspections={inspections} />
<SearchInspections inspections={inspections} />
<DisplayInspections
inspections={inspections}
setSelectedHive={props.setSelectedHive}
setSelectedInspection={props.setSelectedInspection}
/>
</div>
);
};
export default InspectionPage;

How to force "The onFormSubmit function in hbspt.forms.create requires jQuery. It was not run." Error in Gatsby SPA

I'm trying to implement HubspotForm into my SAP. It render's but when I click submit button I get error "The onFormSubmit function in hbspt.forms.create requires jQuery. It was not run."
How can I force this?
My component:
import React from "react"
import style from "./bottomForm.module.sass"
import BackgroundImage from "gatsby-background-image"
import classNames from "../../helpers/classNames"
import HubspotForm from "react-hubspot-form"
import { graphql, useStaticQuery } from "gatsby"
const BottomForm = ({ image, title, children }) => {
const defaultImage = useStaticQuery(graphql`
query {
form_bg: file(relativePath: { eq: "common/form_bg.jpg" }) {
childImageSharp {
fluid(maxWidth: 1920) {
...GatsbyImageSharpFluid_noBase64
}
}
}
}
`)
return (
<BackgroundImage
Tag="section"
className={style.section}
fluid={image || defaultImage.form_bg.childImageSharp.fluid}
id={"bottomForm"}
>
<div className={style.content}>
<h2 className={style.title}>{title}</h2>
<div className={style.form_box}>
<div className={classNames(style.form_column, style.form_info)}>
{children}
</div>
<div className={style.form_column}>
{/*<div id="contactFormBottom" />*/}
<div className={style.form_contact_box}>
<HubspotForm
portalId="9075801"
formId="6ee5300e-5ffe-471d-a400-92b06ca18a11"
onSubmit={() => console.log('Submit!')}
onReady={(form) => console.log('Form ready!')}
loading={<div>Loading...</div>}
/>
</div>
</div>
</div>
</div>
</BackgroundImage>
)
}
export default BottomForm
For me works next solution ---> I add on "onReady" property code which check if jQuery script is in DOM and add it if it isn't. Also I add "onSubmit={() => {}}". Without it error drop down again.
<HubspotForm
portalId="9075800"
formId="11ba4132-6072-4c18-9ea7-f21b70191120"
loading={<div>Loading...</div>}
onReady={() => {
const script = document.createElement('script');
script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js';
let jqueryScript = document.getElementsByTagName('script');
let src = Array.from(jqueryScript).filter(item => item.src === script.src)
if(src.length === 0) {
document.body.appendChild(script)
}
}}
onSubmit={() => {}}
/>
Check this GitHub thread's solution:
import React, { useEffect } from 'react';
....
useEffect(() => {
window.addEventListener('message', handler);
return () => {
window.removeEventListener('message', handler);
}
}, [])
function handler(event) {
if (event.data.type === 'hsFormCallback' && event.data.eventName === 'onFormSubmitted') {
if (event.data.id === 'formidhere')
//do stuff
else if (event.data.id === 'formidhere')
//do stuff
}
}
This is one of the solutions proposed. Another one that I will try to avoid is importing jQuery directly on your project.

Component not rerendering after axios Get (React)

I'm trying to render List of items of my DB using React.Context.
All my request work pretty well.
when i console log my states first I get an empty array and then array with the data that I need but my component is not updating. I have to go to another page an then go back to this page to get the data. I don't really understand why... here are my files..
ArticlesContext.js :
import React, { useState, createContext, useEffect } from 'react';
import axios from 'axios'
export const ArticlesContext = createContext();
export function ArticlesProvider(props) {
const [articles, setArticles] = useState([]);
const [user, setUser] =useState(0)
async function getArticles () {
await axios.get(`/api/publicItem`)
.then(res => {
setArticles(res.data);
})
}
useEffect( () => {
getArticles()
}, [user])
console.log(articles);
return (
<ArticlesContext.Provider value={[articles, setArticles]}>
{props.children}
</ArticlesContext.Provider>
);
}
Inventaire.js :
import React, { useContext, useEffect, useState } from 'react';
import './Inventaire.css';
import { ArticlesContext } from '../../../context/ArticlesContext';
import DeleteAlert from './Delete/Delete';
import Modify from './Modify/Modify';
import Filter from './Filter/Filter';
import axios from 'axios'
import Crud from '../../Elements/Articles/Crud/Crud';
import List from './List/List';
export default function Inventaire() {
const [articles, setArticles] = useContext(ArticlesContext);
const [filter, setFilter] = useState(articles)
console.log(articles);
//list for Inputs
const cat = articles.map(a => a.category.toLowerCase());
const categoryFilter = ([...new Set(cat)]);
const gender = articles.map(a => a.gender.toLowerCase());
const genderFilter = ([...new Set(gender)]);
//Event Listenner
//Uncheck All checkboxes
function UncheckAll() {
const el = document.querySelectorAll("input.checkboxFilter");
console.log(el);
for (var i = 0; i < el.length; i++) {
var check = el[i];
if (!check.disabled) {
check.checked = false;
}
}
}
//SearchBar
const searchChange = (e) => {
e.preventDefault();
const stuff = articles.filter((i) => {
return i.name.toLowerCase().match(e.target.value.toLowerCase())
})
setFilter(stuff)
UncheckAll(true)
}
const Types = (e) => {
if (e.target.checked === true) {
const stuff = filter.filter((i) => {
return i.category.toLowerCase().match(e.target.value.toLowerCase())
})
setFilter(stuff)
console.log(articles);
} else if (e.target.checked === false) {
setFilter(articles)
}
}
const Gender = (e) => {
if (e.target.checked === true) {
const stuff = filter.filter((i) => {
console.log(i.category, e.target.value);
return i.gender.toLowerCase().match(e.target.value.toLowerCase())
})
setFilter(stuff)
} else if (e.target.checked === false) {
setFilter(articles)
}
}
return (
<div className="inventaireContainer">
<input type="text" placeholder="Recherche un Article" onChange={searchChange} />
<div className="inventaireMenu">
<Crud />
<Filter
filter={Types}
categorys={categoryFilter}
genre={genderFilter}
target={Gender}
/>
</div>
<List filter={filter} articles={articles}/>
</div>
)
}
List.js :
import React from 'react';
import DeleteAlert from '../Delete/Delete';
import Modify from '../Modify/Modify';
export default function List({ filter, articles }) {
return (
<div>
{filter.map((details, i) => {
return (
<div className="inventaireBlock" >
<div className="inventaireGrid">
<div className="inventaireItemImg">
<img src={details.image} alt="ItemImg" />
</div>
<h2>{details.name}</h2>
<h3>{details.category}</h3>
<h3>{details.gender}</h3>
<div>
<p>S :{details.sizes[0].s}</p>
<p>M :{details.sizes[0].m}</p>
<p>L :{details.sizes[0].l}</p>
<p>XL :{details.sizes[0].xl}</p>
</div>
<h2> Prix: {details.price}</h2>
<div className="modify">
<Modify details={details._id} />
</div>
<div className="delete" >
<DeleteAlert details={details._id} articles={articles} />
</div>
</div>
</div>
)
})}
</div>
)
}
Thanks for your time

React recaptcha is displayed

I have this code, I would like to make recaptcha hidden,
how to do it, my recaptcha show general conditions with icon in the right lower corner.
Do I need to clean recaptcha?
window['recaptchaVerifier'].clear()
I won't to show this icon, recaptcha logo. I need it
to make 2FA authentication sms + email. It should work
without showing some elements, or is problem that I have
this div?
<div ref={recaptchaWrapperRef}>
<div id="recaptcha-container"></div>
</div>
import { Button } from '#material-ui/core'
import React, { useEffect, useRef } from 'react'
import { auth, provider } from '../firebase/firebase'
import useDeviceDetect from '../utils/useDeviceDetect'
import './Login.scss'
declare global {
interface Window { recaptchaVerifier: any; }
}
function Login(props: any) {
const val = useRef()
const recaptchaWrapperRef = useRef(null);
useEffect(() => {
initialiseRecaptcha()
}, [])
const { isMobile } = useDeviceDetect();
const initialiseRecaptcha = () => {
setTimeout(() => {
if (!window['recaptchaVerifier']) {
window['recaptchaVerifier'] = new auth.RecaptchaVerifier(
"recaptcha-container",
{
'size': "invisible"
}
);
}
}, 2000)
}
const TwoFactorAuthentication = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
smsVerification()
signIn(e)
}
const signIn = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
e.preventDefault()
auth().signInWithPopup(provider)
.then(result => {
localStorage.setItem('user', JSON.stringify(result.user));
window.location.href = '/'
}).catch(error => {
alert(error.message)
})
}
const smsVerification = () => {
if (window['recaptchaVerifier'] != null) {
new auth.PhoneAuthProvider().verifyPhoneNumber("+421944777170", window['recaptchaVerifier'])
.then(function (verificationId) {
var verificationCode = window.prompt('Please enter the verification code' +
', that was sent on mobile device')
if (verificationCode != null) {
return auth.PhoneAuthProvider.credential(verificationId, verificationCode)
}
})
.then(function (phoneCredential) {
if (phoneCredential != null) {
console.log(phoneCredential)
return auth().signInWithCredential(phoneCredential)
}
})
.catch(function (error) {
})
}
}
return (<>
<div className="login">
<div className="login__logo">
<img
src="https://i.pinimg.com/originals/c6/f2/cd/c6f2cd5e0ebf33ff1ae0b01d0407224c.png"
alt="" />
<img
src="https://svgshare.com/i/PTv.svg"
alt="" />
</div>
<Button id="sign-in-button" type="submit" onClick={TwoFactorAuthentication}>
Signin
</Button>
<div ref={recaptchaWrapperRef}>
<div id="recaptcha-container"></div>
</div>
</div>
</>
)
}
export default Login
EDIT:
I have found that I need set visibility:hidden on css of grecaptcha div, but it always rerender and disable my setting.
const hiddenGRecaptcha = () => {
var head = document.getElementsByClassName('grecaptcha-badge')[0] as HTMLElement
if (head !== undefined) {
head.style.visibility = "hidden"
console.log(head)
}
}
this is my new function in typescript to hide recaptcha badge but css are always overwritten don't know where to put it or how to make it persistent.

Resources