-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRandomPage.jsx
More file actions
65 lines (59 loc) · 2.53 KB
/
RandomPage.jsx
File metadata and controls
65 lines (59 loc) · 2.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import React, { useEffect, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
import useSearchableData from '../hooks/useSearchableData';
import Loading from '../components/Loading';
import { useToast } from '../hooks/useToast';
// * `hasNavigated` Ref: I introduced a useRef variable called hasNavigated.
// * Guard Clause: The useEffect now checks hasNavigated.current at the very beginning. If it's already true, it means a
// navigation attempt has been made, and it returns early.
// * Set Ref: hasNavigated.current is set to true just before calling navigate.
//
// This pattern effectively acts as a flag that ensures the navigation logic runs only once, even if React's Strict Mode
// re-runs useEffect in development or if other factors cause multiple renders.
//
// Now, clicking "Random" should only redirect you once! ✅
const RandomPage = () => {
const { items, isLoading } = useSearchableData();
const navigate = useNavigate();
const { addToast } = useToast();
const hasNavigated = useRef(false);
useEffect(() => {
if (hasNavigated.current) return; // Prevent double navigation in StrictMode or on re-render
if (!isLoading && items.length > 0) {
const allNavigableItems = items.filter(
(item) => item.path && item.path !== '/random',
); // Exclude itself
if (allNavigableItems.length > 0) {
const randomIndex = Math.floor(
Math.random() * allNavigableItems.length,
);
const randomItem = allNavigableItems[randomIndex];
hasNavigated.current = true; // Set ref before navigating
navigate(randomItem.path);
addToast({
title: 'Random',
message: `Navigating to ${randomItem.title || randomItem.path}`,
duration: 2000,
});
} else {
hasNavigated.current = true; // Set ref before navigating
navigate('/'); // Fallback to home if no other items exist
addToast({
title: 'Info',
message: 'No random items found, redirecting to home.',
duration: 3000,
});
}
} else if (!isLoading && items.length === 0) {
hasNavigated.current = true; // Set ref before navigating
navigate('/'); // Fallback to home if no items loaded
addToast({
title: 'Info',
message: 'No searchable items loaded, redirecting to home.',
duration: 3000,
});
}
}, [isLoading, items, navigate, addToast]); // Dependency array
return <Loading />; // Show loading spinner while redirecting
};
export default RandomPage;