Pengalihan Next.js Tanpa Mengedipkan Konten

Next.js memprarender halaman statis, lalu hidrasi situs menjadi sisi klien interaktivitas penuh

Itu berarti, pertama kita melihat halaman kita yang merupakan HTML dan CSS, dan sepersekian detik kemudian, kita mendapatkan JavaScript dan semua interaktivitas seperti klik tombol.

Masalah

Dalam Membuat Aplikasi React mengarahkan atau melakukan history.push sebenarnya tidak menjadi masalah karena semua data yang dikirim diambil di sisi klien, termasuk halaman statis (HTML & CSS). Jadi tidak akan ada konten yang berkedip, dan aplikasi akan mengalihkan atau mendorong halaman dengan lancar.

Namun pada Next.js kita mendapatkan halaman statisnya terlebih dahulu, baru setelah selesai hidrasi barulah kode javascript yang melakukan redirecting akan berjalan. Ini menjadi masalah ketika kami membuat halaman dengan penghalang otentikasi karena pengguna yang tidak sah dapat melihat konten secara singkat sebelum dialihkan.

Saya melihat banyak masalah ini bahkan di aplikasi produksi, mungkin mereka masih menutupi data karena sebagian diambil dari sisi klien, tetapi shell terkadang masih muncul. Coba buka situs web ini https://app.splitbee.io/projects/theodorusclarence.com . Anda tidak seharusnya memiliki akses ke halaman ini. Anda akan melihat flash shell dasbor dan hanya setelah flash itu, Anda akan diarahkan ke halaman login.

Splitbee

Ada banyak jawaban yang tersebar di internet untuk menggunakan metode seperti rendering halaman sisi server, dan memanfaatkan cookie dengan menggunakan dangerouslySetInnerHTML di Head.

Metode pemblokiran halaman ini tidak memerlukan semua itu, tetapi kita perlu memiliki pemuat halaman penuh untuk memblokir konten.

Larutan

Saya membuat demo di https://learn-auth-redirect-nextjs.vercel.app/

Anda dapat mencoba membuka halaman, dan langsung membuka learn-auth-redirect-nextjs.vercel.app/blocked . Anda akan melihat pemuat secara singkat, lalu dialihkan ke / route.

Ada 2 pendekatan yang saya temukan.

1. Memeriksa setiap halaman

 import { useEffect } from ' react ' ; import { useRouter } from ' next/router ' ; import { useAuth } from ' @/contexts/auth ' ; import FullPageLoader from ' @/components/FullPageLoader ' ; export default function blocked () { const router = useRouter (); const { isAuthenticated , user , logout , isLoading } = useAuth (); useEffect (() => { if ( ! isLoading && ! isAuthenticated ) { router . push ( ' / ' ); } }, [ isAuthenticated , isLoading ]); if ( isLoading || ! isAuthenticated ) { return < FullPageLoader />; } return ( < div className = 'py-12 space-y-4 layout' > < h1 > YOUR CONTENT THAT SHOULD NOT BE SEEN UNLESS AUTHENTICATED </ h1 > </ div > ); }

Di sini, kita mendapatkan isAuthenticated dari Auth Context, Anda dapat melihat repositori untuk lebih jelasnya.

Kumpulan kode ini akan mengembalikan komponen FullPageLoader terlebih dahulu sambil menunggu halaman dirender dan terhidrasi, kemudian setelah itu, useEffect akan melakukan pemeriksaan jika kita diautentikasi.

Kode ini menggunakan useEffect dalam Konteks Otentikasi, untuk memverifikasi token yang biasanya disimpan di localStorage. Jika Anda ingin melihat pola Konteks Otentikasi ini, saya memiliki potongan kode untuk itu.

Konteks mengembalikan Nilai isLoading, dan kami menampilkan loader saat memuat, sampai kami mendapatkan nilai isAuthenticated.

Pola ini secara efektif akan memblokir konten yang tidak ingin kami berikan kepada pengguna yang tidak sah. Tetapi menggunakan pendekatan pertama, akan menyakitkan untuk menambahkan pola itu ke setiap halaman terotentikasi yang kita miliki. Jadi saya mencoba membuat PrivateRoute, yang serupa dengan pola React Router CRA.

2. Menggunakan PrivateRoute Component

 import { useEffect } from ' react ' ; import { useRouter } from ' next/router ' ; import { useAuth } from ' @/contexts/auth ' ; import FullPageLoader from ' ./FullPageLoader ' ; export default function PrivateRoute ({ protectedRoutes , children }) { const router = useRouter (); const { isAuthenticated , isLoading } = useAuth (); const pathIsProtected = protectedRoutes . indexOf ( router . pathname ) !== - 1 ; useEffect (() => { if ( ! isLoading && ! isAuthenticated && pathIsProtected ) { // Redirect route, you can point this to /login router . push ( ' / ' ); } }, [ isLoading , isAuthenticated , pathIsProtected ]); if (( isLoading || ! isAuthenticated ) && pathIsProtected ) { return < FullPageLoader />; } return children ; }

Dengan menggunakan komponen ini, kita dapat menentukan rute yang ingin kita lindungi di _app.js

 //_app.js import SEO from ' @/next-seo.config ' ; import ' @/styles/globals.css ' ; import { AuthProvider } from ' @/contexts/auth ' ; import PrivateRoute from ' @/components/PrivateRoute ' ; function MyApp ({ Component , pageProps }) { // Add your protected routes here const protectedRoutes = [ ' /blocked-component ' ]; return ( <> < AuthProvider > < PrivateRoute protectedRoutes = { protectedRoutes } > < Component { ... pageProps } /> </ PrivateRoute > </ AuthProvider > </> ); } export default MyApp ;

Saya terbuka untuk semua saran dan kontribusi untuk meningkatkan 🚀. Buka PR di repositori atau email saya di theodorusclarence@gmail.com

Demo

  1. Tanpa menggunakan pemuat halaman penuh & tidak diautentikasi /blocked-unhandled

    Diblokir tidak tertangani

    Seperti yang Anda lihat, teks merah masih berkedip sebentar

  2. Menggunakan pemuat halaman penuh & tidak diautentikasi /blocked-component

    Diblokir tanpa token

    Menggunakan pemuat halaman penuh, tidak ada konten yang akan di-flash

  3. Menggunakan pemuat halaman penuh & diautentikasi dengan memeriksa token

    Diblokir dengan Token

    Menggunakan pemuat halaman penuh akan tetap berfungsi jika mereka memiliki token di localStorage

May 18, 2021

codeorayo

Ampuh! Ini rahasia mengembangkan aplikasi secara instan, tinggal download dan kembangkan. Gabung sekarang juga! Premium Membership [PRIVATE] https://premium.codeorayo.com

Leave a Reply

Your email address will not be published. Required fields are marked *