Search query box doesn't recommend places in Vue automatically - javascript

If you run my below code, it is supposed to open up a website. This works fine, however, when I go to the input box it is supposed to recommend places with the characters given immediately. This isn't working.
I am doing a tutorial and am currently at 12:41 of this video.
https://www.youtube.com/watch?v=5pTzHoliXUQ&list=PL4cUxeGkcC9hfoy8vFQ5tbXO3vY0xhhUZ&index=5
Here is my code:
<template>
<main class="container text-white" >
<div class="pt-4 mb-8 relative">
<input type="text"
v-model = "searchQuery"
#input="getSearchResults"
placeholder="Search for city or state"
class="py-2 px-1 w-full bg-transparent border-b
focus:border-weather-secondary focus:outline-none focus:shadow-[0px_1px_0_0_#004E71]">
<ul class="absolute bg-weather-secondary text-white w-full shadow-md py-2 px-1 top-[66px]">
<li v-for="searchResult in mapboxSearchResults" :key ="searchResult.id" class="py-2 cursor-pointer">
{{searchResult.place_name}}
</li>
</ul>
</div>
</main>
</template>
<script setup>
import { ref } from 'vue';
import axios from 'axios';
const mapboxAPIkey ="pk.eyJ1IjoiYWhhbmFhYSIsImEiOiJjbGJqc3d5NG0xNGd5M3BtbWppcmgyNzE4In0.L-HsHWAbshfvVY_xixizNw"
const searchQuery = ref("");
const queryTimeout = ref(null)
const mapboxSearchResults = ref(null)
const getResults = () => {
clearTimeout(queryTimeout.value)
queryTimeout.value = setTimeout(async() => {
if(searchQuery.value !== ""){
const result = await axios.get(
`https://api.mapbox.com/geocoding/v5/mapbox.places/${searchQuery.value}.json?access_token=${mapboxAPIkey}&types=place`
)
mapboxSearchresults.value = result.data.features
return;
}
mapboxSearchresults.value = null
}, 300)
}
</script>
I tried to run the code with npm run dev in the terminal and everything was working fine up until now.

Related

an array of the time-when the user has clicked on the button.. but the value keeps on changing...Javascript

I want to make an array of the time-when the user has clicked on the button.. but the value keeps on changing...
In the image, only the current time is shown in the array-but i want the list of timess-when the user clicked on the button.. I normally push.. array.push(element) which i used here as well.But it doesnt work..Why is this ?
Plus i used the hydration states and functions to prevent hydration which was occuring .
import React, { useEffect, useState } from 'react'
function Clock() {
const [time, setTime] = useState(new Date().toLocaleTimeString())
const [isHydrated,setIsHydrated] = useState(false);
let startTime=[];
useEffect(() => {
setIsHydrated(true);
}, [])
setTimeout(()=>{
setTime(new Date().toLocaleTimeString())
},1000)
if(!isHydrated) {
return null;
}
const updateElement = (time) =>{
startTime.push(time);
console.log(startTime)
}
return (
<div>
<div className='container flex flex-col'>
<h1 className="text-red-500 p-10">Productivity app</h1>
<div>
<div>
<span className='p-5 font-bold'>time : {time}</span>
</div>
<button
onClick={()=>updateElement(new Date().toLocaleTimeString()) }
className='bg-red-500 hover:bg-red-700 p-10 w-2/5 text-white rounded-full'>Start</button>
</div>
<div className="overflow-x-auto relative mt-5">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<thead className="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
</div>
</div>
</div>
)
}
export default Clock
`
Well, i had looked at some ways.. i want the list of the times when the user clicked on the button so that- i could list them.
In every render the setTimeout will be called and it will create a new timer that will kick in and change the time value

React returns Typerror whenever i add api content

Hi i am making a photography portfolio with strapi as my CMS and graphql to fetch data in my React frontend
the problem is whenever i add a new pic using strapi the entire site crashes and returns
Uncaught TypeError: Cannot read properties of undefined (reading 'gears')
but when i edit Gearfetch variable by removing it and rewriting it all again it starts working untill i add another pic via strapi and then it gives same error again
is there a permanent solution to this ?
my gearfetch.js :
import React from "react";
import { gql, useQuery } from "#apollo/client";
import MyGear from "../pages/MyGear";
function Gearfetch() {
const Geardata = gql`
query Getgears {
gears {
data {
id
attributes {
Name
description
image {
data {
attributes {
formats
}
}
}
}
}
}
}
`;
const data = useQuery(Geardata);
const GearFetch = data.data.gears.data //<-- to fix i have to remove and rewrite this again
console.log(GearFetch)
return (
<div className="">
<div >
<div className="flex justify-center font-mono font-extrabold text-lg mt-6 ">
MyGear
</div>
<div className="flex justify-center">
<div className=" p-4 xl:mt-4 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 md:gap-2 md:p-4 ">
{GearFetch.map((Gears) => (
<div className="p-4">
<MyGear
key={Gears.attributes.Name}
name={Gears.attributes.Name}
description={Gears.attributes.description}
image = {Gears.attributes.image.data[0].attributes?.formats?.medium.url}
/>
</div>
))}
</div>
</div>
</div>
</div>
);
}
export default Gearfetch;

Programmatically Set an href Link in React

I have a product that I want to programatically set a Checkout Session URL and then redirect a user when they click on an tag.
const PlanComponent = () => {
const [tiers, setTiers] = useState([]);
async function CheckoutSessionUrl(tierId) {
var result = null
await CreateCheckoutSession(
"PRODUCT_ID",
tierId,
"UID"
).then(function(response) {
result = response
})
return result;
};
async function LoadProducts() {
var result = []
await GetProducts("PRODUCT_ID").then(function(response) {
for (var i = 0; i < response.length; i++) {
var tier_id = response[i]["tier_id"]
CheckoutSessionUrl(tier_id).then(function(tier_response) {
response[i]["url"] = tier_response;
})
}
console.log("printing tiers");
console.log(response);
return response;
}).then(function(response){
result = response;
setTiers(result)
return result;
});
return result;
}
useEffect(() => {
// Some initialization logic here
LoadProducts().then(function(response) {
console.log("setting tiers")
console.log(response)
//setTiers(response)
})
}, []);
return (
<div className="bg-white">
<div className="max-w-7xl mx-auto py-24 px-4 sm:px-6 lg:px-8">
<div className="sm:flex sm:flex-col sm:align-center">
<h1 className="text-5xl font-extrabold text-gray-900 sm:text-center">Pricing Plans</h1>
<p className="mt-5 text-xl text-gray-500 sm:text-center">
Start building for free, then add a site plan to go live. Account plans unlock additional features.
</p>
</div>
<div className="mt-12 space-y-4 sm:mt-16 sm:space-y-0 sm:grid sm:grid-cols-2 sm:gap-6 lg:max-w-4xl lg:mx-auto xl:max-w-none xl:mx-0 xl:grid-cols-4">
{tiers.map((tier) => (
<div key={tier.name} className="border border-gray-200 rounded-lg shadow-sm divide-y divide-gray-200">
<div className="p-6">
<h2 className="text-lg leading-6 font-medium text-gray-900">{tier.name}</h2>
<p className="mt-4 text-sm text-gray-500">{tier.description}</p>
<p className="mt-8">
<span className="text-4xl font-extrabold text-gray-900">${tier.price}</span>{' '}
<span className="text-base font-medium text-gray-500">/mo</span>
</p>
<a
href={tier.url}
className="mt-8 block w-full bg-gray-800 border border-gray-800 rounded-md py-2 text-sm font-semibold text-white text-center hover:bg-gray-900"
>
Buy {tier.name}
</a>
</div>
<div className="pt-6 pb-8 px-6">
<h3 className="text-xs font-medium text-gray-900 tracking-wide uppercase">What's included</h3>
<ul role="list" className="mt-6 space-y-4">
{tier.users.map((feature) => (
<li key={feature} className="flex space-x-3">
{/*<CheckIcon className="flex-shrink-0 h-5 w-5 text-green-500" aria-hidden="true" />*/}
<span className="text-sm text-gray-500">{feature}</span>
</li>
))}
</ul>
</div>
</div>
))}
</div>
</div>
</div>
)
}
so if you look at the href={tier.url} it's not being set correctly. I feel like I'm not doing this correctly. Would love some feedback on how to actually get this working properly. IT looks like the tier.url new field isn't being set correctly (doesn't exist in the initial request but all the other attributes work).
The other option I wanted to do was when a user clicked a Button, it would generate a URL and redirect a user to that new external url but the navigation kept breaking.
Oh I found out what was happening. I needed to replace
await GetProducts("PRODUCT_ID").then(function(response) {
with
await GetProducts("PRODUCT_ID").then(async function(response) {

Firebase reCaptcha keeps stalling and freezing website - Vuejs, Firebase V9

I've got the following code that should enable recaptcha and allow users to log in using their phone number. However, whenever I add a phone number and click sign in, the site just freezes, the recpatcha box appears but then nothing happens. I can't see any errors from my console.
Vue3 on Vite using Firebase V9
import { ref } from 'vue'
import { getAuth, RecaptchaVerifier, signInWithPhoneNumber } from "firebase/auth"
const auth = getAuth()
const userPhone = ref(null)
const phoneCode = ref('+44')
const conCode = ref('');
const smsSent = ref(false)
const confirmationResult = ref(null)
const initRecaptcha = () => {
setTimeout(()=>{
window.recaptchaVerifier = new RecaptchaVerifier('sign-in-button', {
size: 'invisible',
'callback': (response) => {
// reCAPTCHA solved, allow signInWithPhoneNumber.
console.log(response)
}}, auth)
},1000)
}
initRecaptcha()
const SignIn = async() => {
const appVerifier = window.recaptchaVerifier
const phonenumber = `${phoneCode.value}${userPhone.value}`
console.log(`${phoneCode.value}${userPhone.value}`)
signInWithPhoneNumber(auth, phonenumber, appVerifier)
.then((confirmationresult) => {
// SMS sent. Prompt user to type the code from the message, then sign the
// user in with confirmationResult.confirm(code).
// ...
window.confirmationResult = confirmationresult;
smsSent.value = true
alert('SMS sent')
}).catch((error) => {
// Error; SMS not sent
// ...
window.recaptchaVerifier.render().then(function(widgetId) {
grecaptcha.reset(widgetId);
})
console.log('Theres been an error', error)
});
}
const confirmCode = async() => {
const code = conCode.value
try {
const result = await confirmationResult.value.confirm(code)
// User signed in successfully.
const user = result.user;
console.log('User details are ', user)
// ...
} catch (error) {
// User couldn't sign in (bad verification code?)
// ...
console.log('BIG ERROR', error)
};
}
</script>
<template>
<div class="px-14 mt-12">
<div id="re-element"></div>
<form v-if="smsSent == false" id="sign-in-form">
<!-- Input to enter the phone number -->
<div class="flex relative shadow-md">
<div class="absolute inset-y-0 left-0 pl-3 my-auto align-middle flex text-gray-300 text-center pointer-events-none"><p class="flex items-middle">(+44)0</p></div>
<input
v-model="userPhone" type="tel" id="phone-number"
class="px-3 py-4 flex-1
pl-16 font-extralight text-gray-600 relative bg-opacity-0 bg-transparent border-2 border-gray-900 bg-gray-800outline-none focus:z-10 focus:outline-none w-full"
/>
<label class="absolute top-2.5 ml-4 px-8 pt-1 -z-1 text-normal font-light duration-300 origin-0 text-gray-500" for="phone-number">Enter your phone number...</label>
<!-- Sign-in button -->
<button #click.prevent="SignIn" class="flex-0 px-4 border-2 border-gray-900" id="sign-in-button">Sign-in</button>
</div>
</form>
<form v-else id="verification-code-form">
<!-- Input to enter the verification code -->
<div class="flex">
<input v-model="conCode" class="" type="text" id="verification-code">
<label class="" for="verification-code">Enter the verification code...</label>
</div>
<!-- Button that triggers code verification -->
<button #click.prevent="confirmCode" class="text-grey-800" id="verify-code-button" value="Verify Code">Verify code</button>
<!-- Button to cancel code verification -->
<button class="" id="cancel-verify-code-button">Cancel</button>
</form>
<div id="phone-sign-in-recaptcha"></div>
</div>
</template>
<style scoped>
input:focus-within ~ label,
input:not(:placeholder-shown) ~ label {
#apply transform scale-75 -translate-y-3.5 px-6;
}
input:focus-within ~ label {
#apply text-blue-500;
}
</style>
Am I missing something wildly obvious? I've been stuck of this for some time haha. Thanks in advance.

Next.js - Expected server HTML to contain a matching <div> in <div>

Live example available here
I'm trying to make a basic layout where, on mobiles, only the latest posts appear. On desktop, the left column should be the posts and the right column the top categories and most popular posts.
Here is the layout:
const IndexLayout: React.FC<IndexLayoutProps> = ({}) => {
const cols = useScreenType()
return cols === '2-cols' ? (
<div className="w-full flex justify-between items-start">
<ListPosts data-comp="ListPosts" className="w-4/6" />
<div className="sticky ml-12 w-2/6 flex flex-col">
<TopCategories data-comp="TopCategories" className="w-full" />
<PopularPosts data-comp="PopularPosts" className="mt-4" />
</div>
</div>
) : (
<ListPosts data-comp="ListPosts" className="w-full" />
)
}
Here's the useScreenType hook:
import { useMediaQuery } from 'react-responsive'
export const useScreenType = () => {
const is2Cols = useMediaQuery({ minWidth: 1300 })
const is1Cols = useMediaQuery({ minWidth: 800 })
if (is2Cols) {
return '2-cols'
}
if (is1Cols) {
return '1-cols'
}
return 'fullscreen'
}
And I keep getting this error:
Warning: Expected server HTML to contain a matching <div> in <div>.
div
ListPosts#webpack-internal:///./components/posts/ListPosts.tsx:31:19
div
IndexLayout#webpack-internal:///./components/layout/IndexLayout.tsx:28:149
div
Index#webpack-internal:///./pages/index.tsx:24:149
ApolloProvider#webpack-internal:///./node_modules/#apollo/client/react/context/ApolloProvider.js:13:18
s#webpack-internal:///./node_modules/next-apollo/dist/index.es.js:26:1911
div
div
MyApp#webpack-internal:///./pages/_app.tsx:37:19
ErrorBoundary#webpack-internal:///./node_modules/#next/react-dev-overlay/lib/internal/ErrorBoundary.js:23:47
ReactDevOverlay#webpack-internal:///./node_modules/#next/react-dev-overlay/lib/internal/ReactDevOverlay.js:73:20
Container#webpack-internal:///./node_modules/next/dist/client/index.js:155:20
AppContainer#webpack-internal:///./node_modules/next/dist/client/index.js:643:18
Root#webpack-internal:///./node_modules/next/dist/client/index.js:779:19
Now I think the issue is due to the useScreenType hook not being able to get a width because window isn't defined on the server. But how can I fix this issue? And not only do I get an error, but my HTML renders weirdly.
The final render ends up being something like this (when it renders as '2-cols'):
<div class="flex flex-col justify-start items-start w-full">
<div class="mt-6 w-full"></div>
<div class="mt-4 flex items-center cursor-pointer transform transition hover:scale-105 text-sm">
<div class="w-full p-6 rounded-lg flex flex-col dark:bg-gray-800 shadow-md"></div>
<div class="mt-4 p-6 rounded-lg flex flex-col dark:bg-gray-800 shadow-md"></div>
</div>
</div>
Note: I am using Next.js v10.2.0
Code can be found on GitHub
As you notice, you cant access window object on server, so if you want to server-render something based on window object - you must hardcode these values.
The only thing you can rely on is user-agent in request headers, which gives you some understanding of user device.
For example this way you can detect user device in _app.js:
const device = deviceDetector.detect(isServer() ? ctx.req.headers['user-agent'] : window.navigator.userAgent)
deviceDetector is any kind of device detection implementation based on user agent
For anyone wondering how I fixed this, I ditched the responsive design with logic and switched to CSS. Here is my layout post fix (changed some classes with the lg prefix [documentation]):
const IndexLayout: React.FC<IndexLayoutProps> = ({}) => {
return (
<div className="mt-12 lg:mt-24 w-5/6 mx-auto flex items-start">
<div className="w-full flex justify-between items-start">
<ListPosts className="lg:w-4/6 w-full" />
<div className="hidden sticky ml-12 w-2/6 lg:flex flex-col">
<TopCategories className="w-full" />
<PopularPosts className="mt-4" />
</div>
</div>
</div>
)
}

Categories