Reputation: 17
I'm using Sveltekit & Firebase for my project
I have my meta data in a component that works fine. I'm trying to pass data to use for the meta tags but the metatags run before it can receive the data that i'm passing in on the page.
I've tried having the component inside of if statements, foreach statements, but the meta component always runs before the data is ready. Part of me thinks it's because the onMount is Async, but I need to have it like that for the firebase data collection.
I'm not sure if there is a way for the component to wait for the page data to load before running.
This is my code for my main page which is a dynamic page of [slug].svelte It gets the data that I expect and i've used it on the rest of the page inside of an {#if} statement so I know it works
onMount(async () => {
//Get single document
const setupQuery = query(collection(db, 'setups'), where('slug', '==', urlPath));
const setupQuerySnapshot = await getDocs(setupQuery);
setupQuerySnapshot.forEach((doc) => {
setup = doc.data();
});
});
{#if setup}
<Seo title={`${setup.title} by ${setup.user} - DeskSetups`} />
{:else}
<Seo />
{/if}
And this is my Meta tag component which is working fine for other pages and other dynamic pages.
<script>
import { page } from '$app/stores';
export let title = 'DeskSetups - Your source of desk setup inspiration';
export let description =
"DeskSetups allows you to explore others' setups and the products that make them, whilst also being able to create, share and plan your own.";
export let image = 'https://i.imgur.com/Xc26d2q.png';
export let type = 'website';
$: url = $page.url.href;
</script>
<svelte:head>
<!-- HTML Meta Tags -->
<title>{title}</title>
<meta name="description" content={description} />
<!-- Google / Search Engine Tags -->
<meta itemprop="name" content={title} />
<meta itemprop="description" content={description} />
<meta itemprop="image" content={image} />
<!-- Facebook Meta Tags -->
<meta property="og:url" content={url} />
<meta property="og:type" content={type} />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:image" content={image} />
<!-- Twitter Meta Tags -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={image} />
<!-- Favicon -->
<link rel="icon" type="image/png" href="/favicon.png" />
</svelte:head>
If there is any other info I can provide ill do my best to provide it. Thanks
Upvotes: 0
Views: 44
Reputation: 17
I've managed to figure out my problem. The way I solved it was Passing the data into a +page.server.js page and passing into my [slug].svelte via props.
This way the data gets collected on the backend before the DOM renders and there for not having to wait for the DOM before running any data queries.
Here is my code for the +page.sever.js page. Its most likely a mess but I need to learn/understand it more
import { db } from '$lib/firebase/firebase';
import { collection, doc, getDoc, getDocs } from 'firebase/firestore';
export async function load({ params }) {
const urlPath = params.slug;
let setupData;
let setupDataId;
const querySnapshot = await getDocs(collection(db, 'setups'));
querySnapshot.forEach(async (doc) => {
setupData = doc.data();
if (setupData.slug == urlPath) {
setupData = doc.data();
setupDataId = doc.id;
}
});
const docRef = doc(db, 'setups', `${setupDataId}`);
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
setupData = docSnap.data();
return {
props: {
urlPath,
setupData: structuredClone(setupData)
}
};
} else {
// doc.data() will be undefined in this case
return {
props: {
urlPath
}
};
}
}
Upvotes: 0