The Difference Between params
and props
in Astro and How to Use Them
When developing websites with Astro, I wondered about data passing methods. I became confused about what the two concepts of params
and props
really are. This article summarizes what I researched about the differences between params
and props
and how to use them.
Table of Contents
Problem: The Data Passing Puzzle in Astro
When developing with a new Astro project, don’t you encounter questions like these?
- “When passing data to page components, should I use
params
orprops
?” - “Why can’t I access
Astro.params
in interactive components?” - “What’s the optimal way to pass data to components in dynamic routes?”
To answer these questions, let’s first organize the basic differences.
Basic Differences Between params
and props
Aspect | params | props |
---|---|---|
Source | Dynamic segments from routing (e.g., /blog/[slug].astro ) | Explicitly passed by parent component |
Access Method | Retrieved via Astro.params | Retrieved via Astro.props (received as function arguments) |
Access Scope | Page / Layout files only (not available in client components) | All components (page, layout, client components) |
Main Usage | Data fetching and page generation dependent on URL | Passing values to highly reusable UI components |
Typing | Often manually typed due to dependency on route definition | Easy to define type-safely with interface Props { ... } |
Build vs Runtime | Astro automatically injects by parsing URL | Parent bundles values and injects during rendering |
Pitfalls | - Empty without dynamic routes - Not accessible in client components | - Forgetting to pass / type mismatch - Bloat when passing too much |
Representative Patterns | - Article pages - Multi-language ( [lang]/[...page].astro ) | - Generic cards / buttons - Layout setting values |
Solution: How to Distinguish Usage
Use the following criteria to distinguish usage:
1. URL Dependency-Based Selection
Use params
when URL structure is the primary source of data:
// src/pages/articles/[category]/[id].astro
---
const { category, id } = Astro.params;
// Use values obtained directly from URL for data fetching
const article = await fetchArticle(category, id);
---
Key Point: Effective when URLs represent user state or navigation history.
2. Maximizing Component Reusability
Always use props
for reusable components:
---
// src/components/Alert.astro
interface Props {
type: 'info' | 'warning' | 'error';
message: string;
dismissable?: boolean;
}
const { type, message, dismissable = true } = Astro.props;
---
<div class={`alert alert-${type}`} data-dismissable={dismissable}>
<p>{message}</p>
{dismissable && <button class="close">×</button>}
</div>
Practical Examples:
<Alert type="warning" message="You have unsaved changes" />
<Alert type="error" message="Connection failed" dismissable={false} />
3. Data Fetching and 404 Handling
Consider handling cases where params
values are invalid:
---
// src/pages/products/[id].astro
const { id } = Astro.params;
const product = await getProduct(id);
// Redirect to 404 page if product doesn't exist
if (!product) {
return Astro.redirect('/404');
}
// Or change only the Status Code
if (!product) {
Astro.response.status = 404;
}
---
{product ? (
<ProductDetail item={product} />
) : (
<ProductNotFound id={id} />
)}
4. Maximizing TypeScript Compatibility
Use type definitions for type-safe codebases:
// Type definition for params
export interface ProductParams {
id: string;
category?: string;
}
// Common type definition for props (reusable)
export interface CardProps {
title: string;
description: string;
imageUrl?: string;
isPromoted?: boolean;
}
Implementation Example: Practical Code
Dynamic Blog Article Page Example
---
// src/pages/blog/[slug].astro
import { getCollection } from 'astro:content';
import BlogLayout from '../../layouts/BlogLayout.astro';
import RelatedPosts from '../../components/RelatedPosts.astro';
import ShareButtons from '../../components/ShareButtons.astro';
// 1. Get slug from params
const { slug } = Astro.params;
// 2. Get content
const posts = await getCollection('blog');
const post = posts.find(post => post.slug === slug);
// 3. 404 if article doesn't exist
if (!post) {
return Astro.redirect('/404');
}
// 4. Get related posts (articles with same tags)
const relatedPosts = posts
.filter(p => p.slug !== slug && p.data.tags.some(tag => post.data.tags.includes(tag)))
.slice(0, 3);
// 5. Prepare to render article content
const { Content } = await post.render();
---
<BlogLayout title={post.data.title} description={post.data.description}>
<article class="prose lg:prose-xl mx-auto">
<h1>{post.data.title}</h1>
<div class="metadata">
<time datetime={post.data.date.toISOString()}>
{post.data.date.toLocaleDateString('en-US')}
</time>
<div class="tags">
{post.data.tags.map(tag => (
<a href={`/tags/${tag}`} class="tag">#{tag}</a>
))}
</div>
</div>
<Content />
<!-- Pass necessary data to components via props -->
<ShareButtons
title={post.data.title}
url={`https://myblog.com/blog/${slug}`}
/>
<RelatedPosts posts={relatedPosts} />
</article>
</BlogLayout>
Reusable UI Component Example
---
// src/components/PostCard.astro
interface Props {
title: string;
date: Date;
excerpt: string;
slug: string;
featured?: boolean;
}
const { title, date, excerpt, slug, featured = false } = Astro.props;
const formattedDate = date.toLocaleDateString('en-US');
---
<article class={`card ${featured ? 'card-featured' : ''}`}>
<a href={`/blog/${slug}`}>
<h2>{title}</h2>
<p class="excerpt">{excerpt}</p>
<time datetime={date.toISOString()}>{formattedDate}</time>
</a>
</article>
<style>
.card {
border: 1px solid #eee;
padding: 1.5rem;
border-radius: 8px;
transition: transform 0.2s, box-shadow 0.2s;
}
.card:hover {
transform: translateY(-3px);
box-shadow: 0 10px 20px rgba(0,0,0,0.1);
}
.card-featured {
border-left: 4px solid #7c3aed;
background-color: #f5f3ff;
}
</style>
Common Mistakes and Solutions
Mistake 1: Trying to access params
from client components
---
// ❌ This doesn't work
---
<script>
// Astro.params is not available on the client side
console.log(Astro.params.slug); // Error!
</script>
Solution: Pass necessary values through data attributes
---
const { slug } = Astro.params;
---
<div data-article-id={slug}>
<script>
// Access via data attributes
const container = document.querySelector('[data-article-id]');
const slug = container.dataset.articleId;
console.log('Article slug:', slug);
</script>
</div>
Mistake 2: Omitting props typing
---
// ❌ No types, can't prevent incorrect usage
const { titl } = Astro.props; // Typos won't be warned about
---
Solution: Always define Props interface
---
// ✅ Type-safe props handling
interface Props {
title: string;
description?: string;
}
const { title, description = '' } = Astro.props;
---
Summary: Points to Keep in Mind!
Points for efficient Astro project development!!:
Think of
params
as “input from URL”- Important information related to user navigation
- Use for URL structures that are meaningful for SEO
Design
props
as “component API”- Have explicit interfaces
- Ensure robustness with default values and types
Always be conscious of data flow
- The basic flow is
params
→ data fetching →props
- From URL through database or API to UI components
- The basic flow is
Proper error handling
- Don’t forget to validate
params
input values - Handle 404 and other error states appropriately
- Don’t forget to validate
Following these principles should make your Astro projects surprisingly manageable! 🚀 Even for large sites or projects requiring long-term operation, incorporating these patterns from the beginning should greatly reduce occasions for sighing “This will be hard to fix later…” ✨
Finally: Checklist for Data Management in Astro
I’ve compiled a checklist useful when starting new Astro projects or improving existing ones:
Diagram data flow
- Clarify data flow from URL to components
- Map which values are needed by which components
Create type definitions first
- Create type definitions for
params
andprops
upfront - Decide interface design in advance
- Create type definitions for
Clarify component responsibilities
- Page components: Data fetching and overall structure
- UI components: Focus only on display
Be performance-conscious
- Pass only the minimum necessary properties
- Appropriately divide large data
Write debuggable code
- Separate complex data transformations into independent functions
- Make error location identification easy
Astro is a framework with a unique mental model, but once you understand the concepts of params
and props
, development troubles should decrease!! Probably!