I'm trying to write code so that a supabase full of different graded readers for language learners can be selected from a dropdown, and suited to your language of choice, level and genre etc, with some links in the future to buy them from amazon or the general internet.
I've got this code and refined and refined it, but still after doing npm run dev, after a minute or two my laptop just freezes up and needs a reboot:
'use client';
import { useEffect, useState } from 'react';
type Book = {
id: string;
title: string;
author?: string;
};
const languageOptions = [
{ value: 'spanish', label: 'Spanish' },
{ value: 'french', label: 'French' },
{ value: 'german', label: 'German' },
] as const;
type LanguageValue = (typeof languageOptions)[number]['value'];
export default function HomePage() {
const [books, setBooks] = useState<Book[]>([]);
const [table, setTable] = useState<LanguageValue>('spanish');
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState('');
useEffect(() => {
let active = true;
async function loadBooks() {
try {
setIsLoading(true);
setError('');
const response = await fetch(
/api/books?table=${encodeURIComponent(table)}
);
if (!response.ok) {
throw new Error('Failed to load books');
}
const result = await response.json();
if (!active) return;
setBooks(Array.isArray(result?.data) ? result.data : []);
} catch (err) {
if (!active) return;
setBooks([]);
setError(
err instanceof Error ? err.message : 'Something went wrong'
);
} finally {
if (active) {
setIsLoading(false);
}
}
}
loadBooks();
return () => {
active = false;
};
}, [table]);
return (
<main>
<h1>
Books in{' '}
{languageOptions.find((l) => l.value === table)?.label}
</h1>
<select
value={table}
onChange={(e) =>
setTable(e.target.value as LanguageValue)
}
>
{languageOptions.map((item) => (
<option key={item.value} value={item.value}>
{item.label}
</option>
))}
</select>
{isLoading && <p>Loading...</p>}
{error && <p>{error}</p>}
<ul>
{books.map((book) => (
<li key={book.id}>
{book.title}
{book.author && — ${book.author}}
</li>
))}
</ul>
</main>
);
}