首頁  >  問答  >  主體

有條件地渲染基於Next.js的元件:如何根據請求是否來自已驗證的Firebase使用者?

<p><strong>注意:</strong>我正在使用Next.js 13和<code>app/</code>目錄。 </p> <hr /> <p>我正在學習Firebase和Next.js,我正在努力理解如何解決一個玩具問題。假設我有一個像這樣的<code>Home()</code>組件</p> <p><strong><code>/app/page.jsx</code></strong></p> <pre class="brush:php;toolbar:false;">export default function Home() { return ( <main> <h1>Hello World</h1> <p>只有經過驗證的使用者才能看到這段文字</p> </main> ) }</pre> <p>我的目標是根據請求頁面的使用者是否為已登入使用者有條件地渲染<code><p>...</p></code>中的所有內容。 Firebase使用JWT,Next.js 13在伺服器端呈現此元件,所以我相信這是可能的,但我無法弄清楚如何做到這一點。 </p> <p>我知道onAuthStateChanged,但據我所知,這只能在客戶端使用。 (精明的用戶仍然可以查看這些受保護的內容。)我如何在<em>伺服器端</em>保護這些內容? </p>
P粉616111038P粉616111038443 天前546

全部回覆(1)我來回復

  • P粉037880905

    P粉0378809052023-08-27 12:25:17

    要檢查使用者是否已登錄,您可以使用'onAuthStateChanged'方法。

    將此資訊儲存在元件的狀態中,或使用它來有條件地渲染元件的部分。

    import React, { useEffect, useState } from 'react';
    import firebase from 'firebase/app';
    import 'firebase/auth';
    
    export default function Home() {
      const [user, setUser] = useState(null);
    
      useEffect(() => {
        const unsubscribe = firebase.auth().onAuthStateChanged(user => {
      setUser(user);
      });
        return () => unsubscribe();
      }, []);
    
      return (
        <main>
          <h1>Hello World</h1>
          {user ? (
            <p>authenticated user</p>
          ) : null}
        </main>
      );
    }

    要在伺服器端執行使用者驗證,Next.js提供了'getServerSideProps'來取得使用者的驗證狀態

    import firebase from 'firebase/app';
    import 'firebase/auth';
    
    export default function Home({ user }) {
      return (
        <main>
          <h1>Hello World</h1>
          {user ? (
            <p>authenticated user</p>
          ) : null}
        </main>
      );
    }
    
    export async function getServerSideProps(context) {
      const user = await new Promise((resolve, reject) => {
        firebase.auth().onAuthStateChanged(user => {
          resolve(user);
        });
      });
    
      return {
        props: {
          user,
        },
      };
    }

    更新的解決方案:

    建立一個伺服器端路由

    import firebase from 'firebase/app';
    import 'firebase/auth';
    import express from 'express';
    
    const app = express();
    
    app.get('/api/user', async (req, res) => {
      const user = await new Promise((resolve, reject) => {
        firebase.auth().onAuthStateChanged(user => {
          resolve(user);
        });
      });
    
      res.send(user);
    });
    
    app.listen(3000, () => {
      console.log('Server started at http://localhost:3000');
    });

    客戶端程式碼

    import React, { useState, useEffect } from 'react';
    import axios from 'axios';
    
    export default function Home() {
      const [user, setUser] = useState(null);
    
      useEffect(() => {
        const fetchUser = async () => {
          const res = await axios.get('http://localhost:3000/api/user');
          const user = res.data;
    
          setUser(user);
        };
    
        fetchUser();
      }, []);
    
      return (
        <main>
          <h1>Hello World</h1>
          {user ? (
            <p>authenticated user</p>
          ) : null}
        </main>
      );
    }

    回覆
    0
  • 取消回覆