如何根据登录状态(登录/登出)动态修改应用的title属性?
Great question! The issue with your current code is that React won't automatically re-render your App component when window.accountData changes — since it's a global variable outside React's state management system. Let's fix that with clean, React-friendly approaches tailored for React Admin:
方案1:利用React Admin的内置Auth状态(推荐)
React Admin provides a useAuthState hook that tracks login/logout status and user data automatically. This is the most idiomatic way to handle dynamic title updates here, as it ties directly into the library's built-in state management.
Here's how to adjust your code:
import { useAuthState } from 'react-admin'; const App = () => { // Get current auth state and user data from React Admin const { isAuthenticated, user } = useAuthState(); // Calculate title based on authenticated state and user data const pageTitle = isAuthenticated && user?.accommodation?.name ? `Dashboard - ${user.accommodation.name}` : 'Dashboard'; return ( <Admin theme={theme} customRoutes={customRoutes} menu={Menu} dataProvider={loopbackRestClient(window.apiUrl)} authProvider={authClient()} dashboard={Dashboard} locale="en" i18nProvider={i18nProvider} title={pageTitle} > {/* Your existing routes/components here */} </Admin> ); };
Key Notes:
- Make sure your
authClient()returns the full user object (includingaccommodation.name) in itsgetIdentitymethod. If it doesn't, update your auth provider to store and return that data after login. useAuthStatewill trigger a re-render whenever the login status or user data changes (on successful login/logout), so your title will update automatically.
方案2:监听全局变量变化(if you need to keep using window.accountData)
If you want to stick with window.accountData, you'll need to set up a listener to detect changes and update React state, which will trigger a re-render.
First, modify your login/logout logic to dispatch events when accountData changes:
// After successful login: window.accountData = response.data.accountData; window.dispatchEvent(new Event('accountUpdated')); // After logout: delete window.accountData; window.dispatchEvent(new Event('accountLoggedOut'));
Then update your App component to listen for these events and manage local state:
import { useState, useEffect } from 'react'; const App = () => { const [accommodationName, setAccommodationName] = useState( window.accountData?.accommodation?.name || '' ); useEffect(() => { // Update state when account data changes const handleAccountUpdate = () => { setAccommodationName(window.accountData?.accommodation?.name || ''); }; // Reset state on logout const handleAccountLogout = () => { setAccommodationName(''); }; // Attach event listeners window.addEventListener('accountUpdated', handleAccountUpdate); window.addEventListener('accountLoggedOut', handleAccountLogout); // Clean up listeners on unmount return () => { window.removeEventListener('accountUpdated', handleAccountUpdate); window.removeEventListener('accountLoggedOut', handleAccountLogout); }; }, []); const pageTitle = accommodationName ? `Dashboard - ${accommodationName}` : 'Dashboard'; return ( <Admin // Keep your existing props title={pageTitle} > {/* Your existing routes/components here */} </Admin> ); };
额外优化:规范Auth Provider User Storage
To make方案1 work seamlessly, ensure your authClient() properly stores and returns user data. Here's a quick example of an updated auth provider:
const authClient = () => ({ login: async ({ username, password }) => { const response = await fetch(`${window.apiUrl}/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }), }); if (!response.ok) throw new Error('Login failed'); const { accountData } = await response.json(); // Store user data in localStorage for persistence localStorage.setItem('user', JSON.stringify(accountData)); window.accountData = accountData; return Promise.resolve(); }, logout: async () => { localStorage.removeItem('user'); delete window.accountData; return Promise.resolve(); }, checkAuth: async () => { return localStorage.getItem('user') ? Promise.resolve() : Promise.reject(); }, getIdentity: async () => { const user = JSON.parse(localStorage.getItem('user')); return Promise.resolve(user); }, // Add other required auth methods here (checkError, getPermissions) });
Final Recommendation
Go with 方案1 — it leverages React Admin's built-in tools, avoids global variable side effects, and aligns with React's state management best practices.
内容的提问来源于stack exchange,提问作者user2078023

