23
app/page.tsx
23
app/page.tsx
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useState, useEffect, useCallback, Suspense } from 'react';
|
import { useState, useEffect, useCallback, Suspense } from 'react';
|
||||||
import { useSearchParams, useRouter } from 'next/navigation';
|
import { useSearchParams } from 'next/navigation';
|
||||||
import { Search, Copy, Check, Hash, Key, AlertCircle, Loader2, Database, Link } from 'lucide-react';
|
import { Search, Copy, Check, Hash, Key, AlertCircle, Loader2, Database, Link } from 'lucide-react';
|
||||||
|
|
||||||
interface SearchResult {
|
interface SearchResult {
|
||||||
@@ -48,7 +48,6 @@ function formatNumber(num: number): string {
|
|||||||
|
|
||||||
function HasherContent() {
|
function HasherContent() {
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const router = useRouter();
|
|
||||||
const [query, setQuery] = useState('');
|
const [query, setQuery] = useState('');
|
||||||
const [result, setResult] = useState<SearchResult | null>(null);
|
const [result, setResult] = useState<SearchResult | null>(null);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@@ -56,8 +55,9 @@ function HasherContent() {
|
|||||||
const [copiedField, setCopiedField] = useState<string | null>(null);
|
const [copiedField, setCopiedField] = useState<string | null>(null);
|
||||||
const [stats, setStats] = useState<IndexStats | null>(null);
|
const [stats, setStats] = useState<IndexStats | null>(null);
|
||||||
const [copiedLink, setCopiedLink] = useState(false);
|
const [copiedLink, setCopiedLink] = useState(false);
|
||||||
|
const [initialLoadDone, setInitialLoadDone] = useState(false);
|
||||||
|
|
||||||
const performSearch = useCallback(async (searchQuery: string) => {
|
const performSearch = useCallback(async (searchQuery: string, updateUrl: boolean = true) => {
|
||||||
if (!searchQuery.trim()) return;
|
if (!searchQuery.trim()) return;
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -78,25 +78,30 @@ function HasherContent() {
|
|||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
setResult(data);
|
setResult(data);
|
||||||
|
|
||||||
// Update URL with search query
|
// Update URL with search query (using history API to avoid re-triggering effects)
|
||||||
|
if (updateUrl) {
|
||||||
const newUrl = new URL(window.location.href);
|
const newUrl = new URL(window.location.href);
|
||||||
newUrl.searchParams.set('q', searchQuery.trim());
|
newUrl.searchParams.set('q', searchQuery.trim());
|
||||||
router.replace(newUrl.pathname + newUrl.search, { scroll: false });
|
window.history.replaceState(null, '', newUrl.pathname + newUrl.search);
|
||||||
|
}
|
||||||
} catch (_err) {
|
} catch (_err) {
|
||||||
setError('Failed to perform search. Please check your connection.');
|
setError('Failed to perform search. Please check your connection.');
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}, [router]);
|
}, []);
|
||||||
|
|
||||||
// Load query from URL on mount
|
// Load query from URL on mount (only once)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (initialLoadDone) return;
|
||||||
|
|
||||||
const urlQuery = searchParams.get('q');
|
const urlQuery = searchParams.get('q');
|
||||||
if (urlQuery) {
|
if (urlQuery) {
|
||||||
setQuery(urlQuery);
|
setQuery(urlQuery);
|
||||||
performSearch(urlQuery);
|
performSearch(urlQuery, false);
|
||||||
}
|
}
|
||||||
}, [searchParams, performSearch]);
|
setInitialLoadDone(true);
|
||||||
|
}, [searchParams, performSearch, initialLoadDone]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchStats = async () => {
|
const fetchStats = async () => {
|
||||||
|
|||||||
Referencia en una nueva incidencia
Block a user