I am a new Astro user and I e from vanilla HTML and JS. I'm trying to make a Wikipedia webscraper in Astro. I use a ponent that uses the 'query' prop to fetch data from Wikipedia.
Index.astro
---
import Wiki from "../ponents/Wiki.astro";
---
<title>Hello World</title>
<body class="m-5">
<h1 class="text-3xl text-accent">Enter a query to search from:</h1>
<form id="search-form">
<input
id="query"
type="text"
name="query"
class="rounded border-b-[3px] border shadow-md px-3 py-2 w-96 mt-6 focus:outline-none focus:ring focus:ring-accent focus:ring-opacity-30 text-text"
/>
<button id="form" class="rounded border-2 px-3 py-2">Submit</button>
</form>
<br />
<Wiki query="George Washington" />
</body>
../ponents/Wiki.astro
---
import { load } from "cheerio";
const { query } = Astro.props;
const data = { heading: "", paragraphs: "" };
const response = await fetch(`/${query}`);
const html = await response.text();
const $ = load(html);
// Extract relevant information using Cheerio selectors
const title = $("h1#firstHeading").text();
const content = $("p").text();
data.heading += title;
data.paragraphs += content;
---
<div class="border">
<h1>
{data.heading}
</h1>
<p>
{data.paragraphs}
</p>
</div>
The Wiki ponent works as expected, but how do I manipulate the prop passed to the ponent?
I tried using document.createElement to create a Astro element, but it didn't register as one. I'm guessing its because of the inner piling of Astro or something. I'm pretty sure the way I'm approaching this might be wrong, so please feel free to tell me a different way to achieve the same thing
I am a new Astro user and I e from vanilla HTML and JS. I'm trying to make a Wikipedia webscraper in Astro. I use a ponent that uses the 'query' prop to fetch data from Wikipedia.
Index.astro
---
import Wiki from "../ponents/Wiki.astro";
---
<title>Hello World</title>
<body class="m-5">
<h1 class="text-3xl text-accent">Enter a query to search from:</h1>
<form id="search-form">
<input
id="query"
type="text"
name="query"
class="rounded border-b-[3px] border shadow-md px-3 py-2 w-96 mt-6 focus:outline-none focus:ring focus:ring-accent focus:ring-opacity-30 text-text"
/>
<button id="form" class="rounded border-2 px-3 py-2">Submit</button>
</form>
<br />
<Wiki query="George Washington" />
</body>
../ponents/Wiki.astro
---
import { load } from "cheerio";
const { query } = Astro.props;
const data = { heading: "", paragraphs: "" };
const response = await fetch(`https://en.wikipedia/wiki/${query}`);
const html = await response.text();
const $ = load(html);
// Extract relevant information using Cheerio selectors
const title = $("h1#firstHeading").text();
const content = $("p").text();
data.heading += title;
data.paragraphs += content;
---
<div class="border">
<h1>
{data.heading}
</h1>
<p>
{data.paragraphs}
</p>
</div>
The Wiki ponent works as expected, but how do I manipulate the prop passed to the ponent?
I tried using document.createElement to create a Astro element, but it didn't register as one. I'm guessing its because of the inner piling of Astro or something. I'm pretty sure the way I'm approaching this might be wrong, so please feel free to tell me a different way to achieve the same thing
Share Improve this question edited Mar 5, 2024 at 5:38 VLAZ 29.1k9 gold badges63 silver badges84 bronze badges asked Aug 9, 2023 at 4:09 TsugikuniViTsugikuniVi 111 silver badge3 bronze badges1 Answer
Reset to default 5Astro ponents are rendered to plain HTML and so not dynamic in the browser.
In your example, the following happens:
Your index page renders including the
<Wiki />
ponent, passing in aquery
value.Your
<Wiki />
ponent renders, sees the value ofquery
, fetches the required data, and outputs the resulting HTML.A user loads your page, the page contains just the plain HTML you generated, i.e. for your
<Wiki />
ponent, perhaps something like:<div class="border"> <h1>George Washington</h1> <p>George Washington (February 22, 1732 – December 14, 1799) was...</p> </div>
No JavaScript is sent, all the logic in the
---
block is discarded, so there’s no logic to re-render or use the ponent on the client-side. (This might seem inconvenient, butcheerio
for example is more than 300kB of JavaScript, so being able to use that without sending it to users is a big performance improvement.)
There are a two options here to do what you want:
Write a
<script>
tag that includes all your data fetching and DOM update logic, for example wrapping the default HTML output in a custom element that re-fetches and re-renders when a data attribute changes.Use a dynamic UI framework like Preact, Svelte, Vue etc. and use one of Astro’s hydration directives like
client:visible
to make it load client-side JavaScript.
Both of these approaches let you send the code to the browser for updating and re-rendering a ponent, but with different authoring experiences.