Skip to content

Instantly share code, notes, and snippets.

@anartzdev
Created October 19, 2023 12:20
Show Gist options
  • Save anartzdev/13498ed353f6c05ba5e1e7d8ac1cdb80 to your computer and use it in GitHub Desktop.
Save anartzdev/13498ed353f6c05ba5e1e7d8ac1cdb80 to your computer and use it in GitHub Desktop.
Componente Data Fetching Rest
#alert-year-input {
background: #f5f5b0;
border: 2.5px solid #b0b083;
padding: 1rem;
margin: 10px;
border-radius: 1rem;
color: #68683e;
}
#alert-year-input:hover {
cursor: pointer;
}
import {
component$,
useStore,
Resource,
useResource$,
$,
useSignal,
useStyles$,
} from '@builder.io/qwik';
import styles from './index.css?inline'
export const DataFetchingRest = component$(() => {
useStyles$(styles);
const currentYear = new Date().getFullYear();
const incorrectYear = useSignal(false);
const store = useStore({
year: currentYear,
races: [],
});
const API_URL = 'https://ergast.com/api/f1/';
// https://ergast.com/api/f1/<AÑO>.json
const getF1RacesByYear = $(
async (year: number, controller?: AbortController): Promise<Array<any>> => {
const endPoint = `${year}.json`;
if (year < 1950 || year > currentYear) {
controller?.abort('incorrect year');
incorrectYear.value = true;
store.year = currentYear;
}
const url = `${API_URL}${endPoint}`;
const data = await fetch(url, {
method: 'GET',
signal: controller?.signal,
});
const json: Array<any> = (await data.json())['MRData']['RaceTable'][
'Races'
];
return Array.isArray(json) ? json : [Promise.reject(json)];
}
);
const f1RacesResource = useResource$<any>(({ track, cleanup }) => {
// Usamos `track` para realizar nuevas consultas cuando cambia el año
track(() => store.year);
// La función `cleanup` se ejecuta cuando se está re-ejecutando y
// el controlador `AbortController` puede abortar la operación anterior porque s ha interrumpido.
const abortController = new AbortController();
cleanup(() => abortController.abort());
// Se obtiene el lista de carreras con el año seleccionado.
return getF1RacesByYear(store.year, abortController);
});
return (
<div>
{incorrectYear.value && (
<div id='alert-year-input' onClick$={() => (incorrectYear.value = false)}>
El año introducido debe de ser 1950 (incluido) hasta el año actual
(incluido) que es {currentYear}. Se asigna el actual por defecto
</div>
)}
<div>
<input
type='text'
value={store.year}
maxLength={4}
placeholder='Añadir año entre 1950 y el actual (incluidos) para lista de carreras'
onInput$={(ev) => {
setTimeout(() => {
store.year = +(ev.target as HTMLInputElement).value;
}, 1000);
}}
class='text-l w-96 max-w-full rounded border-0 bg-white px-4 py-4 shadow outline-none placeholder:italic focus:outline-none focus:ring'
/>
</div>
<div id='data'>
<Resource
value={f1RacesResource}
onPending={() => (
<div class='grow animate-pulse rounded-md bg-gray-200 text-left'>
Loading...
</div>
)}
onRejected={(error) => (
<div
class='grow rounded border border-solid border-red-300 bg-red-100 p-4 text-center text-red-500'
role='error-message'
>
Error: {error.message}
</div>
)}
onResolved={(result) => (
<>
<div class='mr-4 season-data'>
Current Year: {result && result[0].season}
</div>
<div class='text-left' role='display-message'>
<ul>
{result &&
result.map((race: any) => {
return (
<li
class='race-item'
key={`race_${store.year}_${race.round}`}
>
{race.round} - {race.raceName}
</li>
);
})}
</ul>
</div>
</>
)}
/>
</div>
</div>
);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment