Next.js:如何复用getServerSideProps获取用户信息并全局共享至各页面
Got it, let's solve this problem. You're right that getServerSideProps doesn't work directly in _app.js for Next.js Pages Router, but there are two solid approaches to avoid repeating your user-fetching logic across every page while making the user data accessible everywhere.
getInitialProps in _app.js + React Context Since getServerSideProps isn't supported in _app.js, you can use getInitialProps instead—it runs on every request (both server and client) and lets you fetch data once at the app level. Pair this with React Context to make the user data available to all pages and components without passing props manually.
Step 1: Create a User Context
First, set up a context to hold and distribute the user data:
// contexts/UserContext.js import { createContext, useContext } from 'react'; const UserContext = createContext(null); export const UserProvider = UserContext.Provider; export const useUser = () => useContext(UserContext);
Step 2: Update _app.js with getInitialProps
Modify your _app.js to fetch the user data in getInitialProps, then pass it through the context provider:
// pages/_app.js import axios from 'axios'; import { UserProvider } from '../contexts/UserContext'; function MyApp({ Component, pageProps, user }) { return ( <UserProvider value={user}> <Component {...pageProps} /> </UserProvider> ); } MyApp.getInitialProps = async ({ req }) => { let user = null; try { // Reuse your existing fetch logic here const response = await axios.get("http://localhost:4000/api/auth/status", { withCredentials: true, headers: { // Use optional chaining to avoid errors on client-side renders Cookie: `connect.sid=${req?.cookies["connect.sid"]}` }, }); user = response.data; } catch (error) { // Handle cases where the user isn't logged in or the request fails console.error('Failed to fetch user data:', error); } return { user }; }; export default MyApp;
Step 3: Access User Data Anywhere
Now you can pull the user data into any page or component using the useUser hook:
// pages/profile.js import { useUser } from '../contexts/UserContext'; export default function ProfilePage() { const user = useUser(); if (!user) { return <p>Please log in to view your profile.</p>; } return ( <div> <h1>Welcome, {user.username}!</h1> <p>Email: {user.email}</p> </div> ); }
If you prefer to pass the user data directly as props to pages (instead of using Context), create an HOC that encapsulates the getServerSideProps logic. This way you only write the fetch code once, then wrap any page that needs the user data.
Step 1: Create the HOC
// hoc/withUser.js import axios from 'axios'; export const withUser = (PageComponent) => { const WithUserPage = (props) => <PageComponent {...props} />; WithUserPage.getServerSideProps = async ({ req }) => { let user = null; try { const response = await axios.get("http://localhost:4000/api/auth/status", { withCredentials: true, headers: { Cookie: `connect.sid=${req.cookies["connect.sid"]}` }, }); user = response.data; } catch (error) { console.error('Failed to fetch user:', error); } // Merge with any existing getServerSideProps from the page const pageProps = typeof PageComponent.getServerSideProps === 'function' ? await PageComponent.getServerSideProps({ req }) : {}; return { props: { ...pageProps, user, }, }; }; return WithUserPage; };
Step 2: Use the HOC on Pages
Wrap your page components with the withUser HOC to inject the user prop:
// pages/dashboard.js import { withUser } from '../hoc/withUser'; function DashboardPage({ user }) { if (!user) { return <p>You need to log in to access the dashboard.</p>; } return <h1>Dashboard for {user.name}</h1>; } // Wrap the page with the HOC export default withUser(DashboardPage);
Key Notes
- Error Handling: Both solutions include error catching to prevent your app from crashing if the auth request fails (e.g., user isn't logged in).
- Client vs Server: The
reqobject is only available on the server, so using optional chaining (req?.cookies) avoids errors during client-side navigation. - Next.js 13+ App Router: If you're using the newer App Router, this approach changes—you'd use Server Components or middleware instead. But since you're working with
_app.js, these Pages Router solutions are perfect.
内容的提问来源于stack exchange,提问作者Pie

