From 398c4a2dd2f15f365d900d213324532db6943a68 Mon Sep 17 00:00:00 2001 From: Kenneth Kalmer Date: Mon, 25 Nov 2024 15:11:24 +0000 Subject: [PATCH] refactor: Status component rebuilt with SWR Main reason is to have only a single ajax request for status data on the page, no matter how many status icons are embedded. Also extract the icon portion into its own StatusIcon component that can be better used in other components, especially inside other anchor tags --- src/core/Status.tsx | 59 +++++++++++++----------------- src/core/Status/Status.stories.tsx | 45 +++++++++++++++++++---- 2 files changed, 62 insertions(+), 42 deletions(-) diff --git a/src/core/Status.tsx b/src/core/Status.tsx index c3f9c9ee9..1f0bfd3e0 100644 --- a/src/core/Status.tsx +++ b/src/core/Status.tsx @@ -1,4 +1,6 @@ -import React, { useEffect, useState } from "react"; +import React from "react"; +import useSWR from "swr"; +import clsx from "clsx"; const indicatorClass = (indicator?: string) => { switch (indicator) { @@ -17,41 +19,34 @@ const indicatorClass = (indicator?: string) => { } }; +export const StatusIcon = ({ + statusUrl, + refreshInterval = 1000 * 60, +}: { + statusUrl: string; + refreshInterval?: number; +}) => { + const fetcher = (url: string) => fetch(url).then(res => res.json()) + const { data, error, isLoading } = useSWR(statusUrl, fetcher, { refreshInterval}) + + return ( + + + + ); +}; + const Status = ({ statusUrl, additionalCSS, + refreshInterval = 1000 * 60, }: { statusUrl: string; additionalCSS?: string; + refreshInterval?: number; }) => { - const [data, setData] = useState<{ status: { indicator: string } } | null>( - null, - ); - - useEffect(() => { - let interval: NodeJS.Timeout; - - if (statusUrl !== "") { - const fetchData = async () => { - try { - const response = await fetch(statusUrl); - const jsonData = await response.json(); - setData(jsonData); - } catch (error) { - console.error("Error fetching status data:", error); - } - }; - - fetchData(); - - interval = setInterval(fetchData, 60000); // Fetch data every minute - } - - return () => { - clearInterval(interval); - }; - }, [statusUrl]); - return ( - - - + ); }; diff --git a/src/core/Status/Status.stories.tsx b/src/core/Status/Status.stories.tsx index 91c7b2423..ffee760b5 100644 --- a/src/core/Status/Status.stories.tsx +++ b/src/core/Status/Status.stories.tsx @@ -1,5 +1,6 @@ import React from "react"; import { delay, http, HttpResponse } from "msw"; +import { SWRConfig } from 'swr' import Status from "../Status"; const statusUrl = "https://ntqy1wz94gjv.statuspage.io/api/v2/status.json"; @@ -29,10 +30,14 @@ export const Loading = { }, }, }, - render: () => , + render: () => ( + new Map() }}> + + + ), }; -const mockParametersWithStatus = (indicator) => { +const mockParametersWithStatus = (indicator: string) => { return { msw: { handlers: { @@ -52,30 +57,54 @@ const mockParametersWithStatus = (indicator) => { export const None = { parameters: mockParametersWithStatus("none"), - render: () => , + render: () => ( + new Map() }}> + + + ), }; export const Operational = { parameters: mockParametersWithStatus("operational"), - render: () => , + render: () => ( + new Map() }}> + + + ), }; export const Minor = { parameters: mockParametersWithStatus("minor"), - render: () => , + render: () => ( + new Map() }}> + + + ), }; export const Major = { parameters: mockParametersWithStatus("major"), - render: () => , + render: () => ( + new Map() }}> + + + ), }; export const Critical = { parameters: mockParametersWithStatus("critical"), - render: () => , + render: () => ( + new Map() }}> + + + ), }; export const Unknown = { parameters: mockParametersWithStatus("unknown"), - render: () => , + render: () => ( + new Map() }}> + + + ), };