Add Child Resource Navigation
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 35/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Đình trệ
- Công nghệ
- react, typescript
- Lĩnh vực
- frontend
Hướng nghiên cứu
Bắt đầu từ entry point useCollection hiện có và so sánh API useStacChildren được đề xuất với các pattern hook hiện tại của repository. Bổ sung coverage cho các catalog con, collection, item, relation tùy chỉnh, trạng thái loading, lỗi, kết quả rỗng và query bị vô hiệu hóa; hoàn thành khi hook phân tách các resource có kiểu và hỗ trợ các pattern browser và lazy-loading được tài liệu hóa.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Problem
STAC catalogs and collections contain links to child resources (child catalogs, collections, or items). Currently, stac-react has no built-in way to:
- Fetch all child resources from a parent
- Navigate catalog hierarchies
- Browse collections within a catalog
- Fetch items linked from a collection
Users must manually parse links and create their own queries, duplicating logic across applications.
Current Behavior
// Must manually parse links and fetch
const { collection } = useCollection('my-collection');
if (collection?.links) {
const childLinks = collection.links.filter(l => l.rel === 'child');
// Now what? Manually fetch each one?
}
No built-in way to fetch child resources automatically.
Desired Behavior
import { useStacChildren } from '@developmentseed/stac-react';
function CatalogBrowser({ catalog }) {
const { catalogs, collections, isLoading, error } = useStacChildren(catalog);
return (
<div>
<h2>Child Catalogs</h2>
{catalogs?.map(cat => <CatalogCard key={cat.id} catalog={cat} />)}
<h2>Collections</h2>
{collections?.map(col => <CollectionCard key={col.id} collection={col} />)}
</div>
);
}
Use Cases from stac-map
stac-map has useStacChildren that:
const { catalogs, collections } = useStacChildren({
value, // Any STAC resource
enabled: !!value && !collectionsLink,
});
// Automatically:
// 1. Finds all links with rel="child"
// 2. Fetches each child resource
// 3. Separates catalogs from collections
// 4. Returns typed arrays
Proposed Solution
Hook Signature
type UseStacChildrenOptions = {
/** The parent STAC resource (catalog, collection, or item) */
value?: StacCatalog | StacCollection | StacItem;
/** Enable/disable the queries */
enabled?: boolean;
/** Which link relations to follow (default: ['child', 'item']) */
relations?: string[];
};
type UseStacChildrenResult = {
/** Child catalogs found */
catalogs?: StacCatalog[];
/** Child collections found */
collections?: StacCollection[];
/** Child items found */
items?: StacItem[];
/** All children (mixed types) */
children?: (StacCatalog | StacCollection | StacItem)[];
/** Loading state */
isLoading: boolean;
/** Error state */
error?: Error;
};
function useStacChildren(
options: UseStacChildrenOptions
): UseStacChildrenResult;
Implementation
import { useQueries } from '@tanstack/react-query';
import { useMemo } from 'react';
function useStacChildren({
value,
enabled = true,
relations = ['child', 'item'],
}: UseStacChildrenOptions): UseStacChildrenResult {
// Find child links
const childLinks = useMemo(() => {
if (!value?.links) return [];
return value.links.filter(link => relations.includes(link.rel));
}, [value, relations]);
// Fetch all children in parallel
const results = useQueries({
queries: childLinks.map(link => ({
queryKey: ['stac-value', link.href],
queryFn: async () => {
const response = await fetch(link.href, {
headers: { 'Accept': 'application/json' },
});
if (!response.ok) {
throw new Error(`Failed to fetch ${link.href}: ${response.statusText}`);
}
return response.json();
},
enabled: enabled && !!value,
retry: false,
})),
combine: (results) => ({
data: results.map(r => r.data).filter(Boolean),
isLoading: results.some(r => r.isLoading),
error: results.find(r => r.error)?.error,
}),
});
// Separate by type
return useMemo(() => {
const catalogs: StacCatalog[] = [];
const collections: StacCollection[] = [];
const items: StacItem[] = [];
for (const child of results.data) {
switch (child?.type) {
case 'Catalog':
catalogs.push(child);
break;
case 'Collection':
collections.push(child);
break;
case 'Feature':
items.push(child);
break;
}
}
return {
catalogs: catalogs.length > 0 ? catalogs : undefined,
collections: collections.length > 0 ? collections : undefined,
items: items.length > 0 ? items : undefined,
children: results.data,
isLoading: results.isLoading,
error: results.error,
};
}, [results.data, results.isLoading, results.error]);
}
Example Usage Patterns
1. Catalog Browser
function CatalogViewer({ catalog }) {
const { catalogs, collections, isLoading } = useStacChildren({
value: catalog
});
if (isLoading) return <Loading />;
return (
<div>
{catalogs && (
<section>
<h2>Subcatalogs ({catalogs.length})</h2>
{catalogs.map(cat => (
<CatalogCard key={cat.id} catalog={cat} />
))}
</section>
)}
{collections && (
<section>
<h2>Collections ({collections.length})</h2>
{collections.map(col => (
<CollectionCard key={col.id} collection={col} />
))}
</section>
)}
</div>
);
}
2. Recursive Catalog Tree
function CatalogTree({ catalog, depth = 0 }) {
const { catalogs, collections } = useStacChildren({
value: catalog,
enabled: depth < 3, // Limit depth
});
return (
<div style={{ marginLeft: depth * 20 }}>
<h3>{catalog.title || catalog.id}</h3>
{collections?.map(col => (
<CollectionItem key={col.id} collection={col} />
))}
{catalogs?.map(cat => (
<CatalogTree key={cat.id} catalog={cat} depth={depth + 1} />
))}
</div>
);
}
3. Collection Items
function CollectionItemsGrid({ collection }) {
const { items, isLoading } = useStacChildren({
value: collection,
relations: ['item'], // Only fetch items
});
return (
<div className="grid">
{items?.map(item => (
<ItemCard key={item.id} item={item} />
))}
</div>
);
}
4. Conditional Loading
function ConditionalChildren({ value, expanded }) {
const { catalogs, collections } = useStacChildren({
value,
enabled: expanded, // Only fetch when expanded
});
// Children only load when user expands the section
}
Advanced Features
Custom Link Following
// Follow any custom link relations
const { children } = useStacChildren({
value: catalog,
relations: ['child', 'item', 'derived_from'],
});
Progress Tracking
function useStacChildrenWithProgress(value) {
const childLinks = value?.links?.filter(l => l.rel === 'child') || [];
const [completed, setCompleted] = useState(0);
const results = useQueries({
queries: childLinks.map(link => ({
// ... query config
onSuccess: () => setCompleted(c => c + 1),
})),
});
return {
...results,
progress: childLinks.length > 0 ? completed / childLinks.length : 0,
};
}
Benefits
- ✅ Automatic child resource fetching
- ✅ Parallel loading for performance
- ✅ Type separation (catalogs vs collections vs items)
- ✅ Enables catalog tree navigation
- ✅ Simplifies recursive browsing
- ✅ Leverages React Query caching
Performance Considerations
- Fetches all children in parallel (not sequential)
- Respects React Query cache (won't refetch)
enabledprop allows lazy loading- Consider pagination for large child sets (future enhancement)
Breaking Changes
None - this is new functionality.
Testing Requirements
- Test with catalogs containing children
- Test with collections containing items
- Test type separation logic
- Test enabled/disabled state
- Test error handling for failed child fetches
- Test with empty/no children
- Test custom relations
- Test parallel loading performance
Documentation Requirements
- Document the hook API
- Provide catalog browser example
- Show recursive tree pattern
- Document performance characteristics
- Show lazy loading patterns
- Document custom link relations
- Ngôn ngữ chính
- TypeScript
- Star
- 34
- Fork
- 4
- Chỉ số merge pull request
- Không có pull request nào được merge trong 30 ngày
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của developmentseed/stac-react
-
Move to NPM trusted publishingĐang mở
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 55/100
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
-
Add Flexible Search HookĐang mở
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 30/100
-
Add File Upload SupportĐang mở
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 30/100
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 42/100
Tất cả issue của developmentseed/stac-react
Issue tương tự
-
enhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
Maintainer thường phản hồi trong vòng 1 ngày
-
[Bug] remember() with special characters in namespace hangs until timeout instead of returning 400Đang mởbug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
MystenLabs/MemWal#1133 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug user-priority/P2
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 92/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 Dưới một giờ Mức phù hợp với người mới 88/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
Effect-TS/effect#8881 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày