Cara Menampilkan Flash Message di Remix Setelah Form Submission - Panduan Praktis

Dalam artikel ini, kita akan mempelajari bagaimana menampilkan flash message di framework Remix setelah form submission. Flash message adalah pesan singkat yang muncul untuk memberi tahu pengguna tentang hasil dari aksi yang mereka lakukan, seperti berhasil mendaftar atau masuk ke akun.

Langkah 1: Buat Session Wrapper

Langkah pertama adalah membuat session wrapper yang dapat digunakan untuk menyimpan dan mengelola flash message. Buat file baru app/utils/sessions/flash.ts dan tambahkan kode berikut:

import { createCookieSessionStorage } from '@remix-run/node';

// Dapatkan secret untuk cookie dari environment variables
let secret = process.env.COOKIE_SECRET || 'default';

if (secret === 'default') {
  console.warn('🚨 No COOKIE_SECRET set, the app is insecure');
  secret = 'session-secret';
}

export const { getSession, commitSession, destroySession } = createCookieSessionStorage({
  cookie: {
    name: '__session',
    httpOnly: true,
    path: '/',
    sameSite: 'lax',
    secure: process.env.NODE_ENV === 'production',
    maxAge: 60,
    secrets: [secret],
  },
});

// Fungsi untuk mendapatkan flash message dari sesi
export async function getFlashMessage(request: Request) {
  const session = await getSession(request.headers.get('Cookie'));
  const message = session.get('message') || null;
  return { message, destroy: await destroySession(session) };
}

// Fungsi untuk set flash message di sesi
export async function setFlashMessage(request: Request, message: string) {
  const session = await getSession(request.headers.get('Cookie'));
  session.flash('message', message);
  return await commitSession(session);
}

Pada bagian ini, kita menggunakan fungsi createCookieSessionStorage untuk membuat penyimpanan sesi yang menggunakan cookie. Cookie ini menyimpan data sesi pengguna dan memiliki beberapa konfigurasi penting seperti keamanan dan umur cookie.

  • Metode getFlashMessage digunakan untuk mendapatkan pesan dari sesi dan langsung membuka sesi tersebut.
  • Metode setFlashMessage digunakan untuk menetapkan pesan di sesi yang akan diambil pada permintaan berikutnya.

Langkah 2: Tambahkan Route register

Tambahkan route baru register untuk membuat pengguna baru dengan form. Route ini akan menangani form submission dan mengarahkan pengguna ke halaman login dengan flash message.

Buat file baru app/routes/register/route.tsx dengan kode berikut:

import { redirect, type ActionFunctionArgs, type MetaFunction } from '@remix-run/node';
import { Form } from '@remix-run/react';
import { Text, TextLink } from '~/components/text';
import { appName, logoUrl } from '~/utils/helpers';
import { setFlashMessage } from '~/utils/sessions/flash';
import { registerAction } from './action'; // Fungsi yang menangani pembuatan pengguna baru

export const meta: MetaFunction = () => {
  return [{ title: `Sign Up - ${appName}` }];
};

export async function action({ request }: ActionFunctionArgs) {
  const { errors, message } = await registerAction(request);

  if (!errors) {
    return redirect('/login', {
      headers: {
        'Set-Cookie': await setFlashMessage(request, message),
      },
    });
  }

  return { errors };
}

export default function Register() {
  return (
    <div className="flex min-h-full flex-1 flex-col justify-center px-6 py-12 lg:px-8">
      <div className="sm:mx-auto sm:w-full sm:max-w-sm">
        <img className="mx-auto h-10 w-auto" src={logoUrl} alt={appName} />
        <h2 className="mt-10 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900 dark:text-white">
          Create an account
        </h2>
      </div>

      <div className="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
        <Form method="post" className="bg-white px-6 py-12 shadow sm:rounded-lg sm:px-12 dark:bg-zinc-900">
          <input type="text" name="name" placeholder="Name" className="input-class" required />
          <input type="email" name="email" placeholder="Email" className="input-class" required />
          <input type="password" name="password" placeholder="Password" className="input-class" required />
          <button type="submit" className="btn-class">Create User</button>
        </Form>

        <Text className="mt-10 text-center">
          Already have an account? <TextLink href="/login">Sign in here</TextLink>.
        </Text>
      </div>
    </div>
  );
}

Metode registerAction menangani pembuatan pengguna baru dan menetapkan error dan pesan sukses. Jika tidak ada error, pengguna akan diarahkan ke halaman login dengan flash message yang telah diset di sesi.

Langkah 3: Tambahkan Route login

Tambahkan route baru login untuk menampilkan flash message. Loader di route ini akan mengambil flash message dari sesi dan menampilkannya di halaman login.

Buat file baru app/routes/login/route.tsx dengan kode berikut:

import { LoaderFunctionArgs, json, type MetaFunction } from '@remix-run/node';
import { Form, useLoaderData } from '@remix-run/react';
import { Badge } from '~/components/badge';
import { Text, TextLink } from '~/components/text';
import { appName, logoUrl } from '~/utils/helpers';
import { getFlashMessage } from '~/utils/sessions/flash';

export const meta: MetaFunction = () => {
  return [{ title: `Sign In - ${appName}` }];
};

export async function loader({ request }: LoaderFunctionArgs) {
  const session = await getFlashMessage(request);

  return json(
    { message: session.message },
    {
      headers: {
        'Set-Cookie': session.destroy,
      },
    }
  );
}

export default function Login() {
  const { message } = useLoaderData<typeof loader>();

  return (
    <div className="flex min-h-full flex-1 flex-col justify-center px-6 py-12 lg:px-8">
      <div className="text-center sm:mx-auto sm:w-full sm:max-w-sm">
        <img className="mx-auto h-10 w-auto" src={logoUrl} alt={appName} />
        <h2 className="mt-10 text-2xl font-bold leading-9 tracking-tight text-gray-900 dark:text-white">
          Sign in to your account
        </h2>
        {message && (
          <Badge color="cyan" className="text-center">
            {message}
          </Badge>
        )}
      </div>

      <div className="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
        <Form method="POST" className="bg-white px-6 py-12 shadow sm:rounded-lg sm:px-12 dark:bg-zinc-900">
          <input type="email" name="email" placeholder="Email" className="input-class" required />
          <input type="password" name="password" placeholder="Password" className="input-class" required />
          <button type="submit" className="btn-class">Sign In</button>
        </Form>

        <Text className="mt-10 text-center">
          Not a member? <TextLink href="/register">Sign up here</TextLink>.
        </Text>
      </div>
    </div>
  );
}

Loader ini menggunakan fungsi getFlashMessage untuk mendapatkan pesan dari sesi dan secara otomatis menghancurkan sesi tersebut setelah pesan diambil. Pesan ini kemudian ditampilkan menggunakan komponen Badge.

Kesimpulan

Dengan mengikuti langkah-langkah di atas, Anda sekarang dapat menambahkan fitur flash message di aplikasi Remix Anda. Ini memungkinkan pemberian umpan balik yang lebih baik kepada pengguna setelah mereka melakukan tindakan tertentu seperti registrasi atau login.

Referensi:

  1. Show a Flash Message in Remix After Form Submission