#Creating a global alert component

4 messages · Page 1 of 1 (latest)

sterile ridge
#

I want to create an alert component that all routes can use. Only one alert can be displayed at a time and it will always be in the same position regardless of the current route. Additionally, I should be able to close the current alert without preventing future alerts from popping up. What I've done is place the Alert component as a child of the root layout

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body className={`${inter.className} bg-black text-white`}>
        {children}
        <Suspense>
          <Alert>
            <svg
              xmlns="http://www.w3.org/2000/svg"
              fill="none"
              viewBox="0 0 24 24"
              strokeWidth="1.5"
              stroke="currentColor"
              height="24"
              width="24"
            >
              <path
                strokeLinecap="round"
                strokeLinejoin="round"
                d="M6 18 18 6M6 6l12 12"
              />
            </svg>
          </Alert>
        </Suspense>
      </body>
    </html>
  );
}

Instead of using useState and passing the setter to all the components that need it which would turn everything into client components, I decided I will read the error param from the search params. I can close the alert by setting the error param to none.

export default function Alert({ children }: { children: React.ReactNode }) {
  const searchParams = useSearchParams();
  const pathName = usePathname();
  const router = useRouter();
  const error = searchParams.get('error');
  if (error) {
    const closeAlert = () => {
      const newParams = new URLSearchParams(searchParams);
      newParams.delete('error');
      router.push(`${pathName}?${newParams.toString()}`);
    };
    return (
      <AlertBody className="bg-red-600" message={error} closeAlert={closeAlert}>
        {children}
      </AlertBody>
    );
  }
  return;
}
astral rampartBOT
#

🔎 This post has been indexed in our web forum and will be seen by search engines so other users can find it outside Discord

🕵️ Your user profile is private by default and won't be visible to users outside Discord, if you want to be visible in the web forum you can add the "Public Profile" role in id:customize

✅ You can mark a message as the answer for your post with Right click -> Apps -> Mark Solution
(if you don't see the option, try refreshing Discord with Ctrl + R)

sterile ridge
#

So now whenever I catch an error, I will set the error param to the message I want. The slight problem with this is that whenever I close the alert button, it deletes the error param and makes a request to the backend with new URL. I want to avoid this unnecessary request. Is there a better approach to this?

#

Alert body component

import { useState } from 'react';
export default function AlertBody({
  className,
  message,
  children,
  closeAlert,
}: {
  className: string;
  message: string;
  children: React.ReactNode;
  closeAlert?: () => void;
}) {
  // const [display, setDisplay] = useState('flex');
  return (
    <div
      className={`${className} absolute bottom-8 left-1/2 flex translate-x-[-50%] gap-x-2 rounded-xl px-4 py-2 text-center align-middle font-medium`}
    >
      <button onClick={closeAlert}>{children}</button>
      {/* <button onClick={() => setDisplay('hidden')}>{children}</button> */}

      {message}
    </div>
  );
}