1
1
import type { Control , ControlMode } from './core/useACL' ;
2
2
import type { IndexRouteObject , NonIndexRouteObject , RouteMatch } from 'react-router-dom' ;
3
3
4
- import { nth } from 'lodash' ;
5
- import React from 'react' ;
4
+ import { isFunction , isUndefined , nth } from 'lodash' ;
5
+ import React , { useEffect } from 'react' ;
6
6
import { useTranslation } from 'react-i18next' ;
7
7
import { matchRoutes , Navigate , renderMatches , useLocation } from 'react-router-dom' ;
8
8
9
9
import { useACLGuard , useTokenGuard } from './Routes.guard' ;
10
10
import { AppFCPLoader } from './components' ;
11
11
import { ROUTES_ACL } from './config/acl' ;
12
- import { LOGIN_PATH } from './config/other' ;
13
- import { usePageTitle } from './hooks' ;
12
+ import { APP_NAME , LOGIN_PATH } from './config/other' ;
14
13
import AppHomeRoute from './routes/Home' ;
15
14
import AppExceptionRoute from './routes/exception/Exception' ;
16
15
import AppLayout from './routes/layout/Layout' ;
@@ -25,8 +24,20 @@ const ROUTES = {
25
24
'/test/http' : React . lazy ( ( ) => import ( './routes/test/http/Http' ) ) ,
26
25
} ;
27
26
27
+ const TITLE_CONFIG : {
28
+ default : string ;
29
+ separator : string ;
30
+ prefix ?: string ;
31
+ suffix ?: string ;
32
+ } = {
33
+ default : APP_NAME ,
34
+ separator : ' - ' ,
35
+ suffix : APP_NAME ,
36
+ } ;
37
+
28
38
export interface RouteStateContextData {
29
39
matchRoutes : RouteMatch < string , RouteItem > [ ] | null ;
40
+ title ?: string ;
30
41
}
31
42
export const RouteStateContext = React . createContext < RouteStateContextData > ( {
32
43
matchRoutes : null ,
@@ -35,7 +46,7 @@ export const RouteStateContext = React.createContext<RouteStateContextData>({
35
46
export type CanActivateFn = ( route : RouteItem ) => true | React . ReactElement ;
36
47
37
48
export interface RouteData {
38
- title ?: string ;
49
+ title ?: string | ( ( params : any ) => string ) ;
39
50
acl ?:
40
51
| {
41
52
control : Control | Control [ ] ;
@@ -173,6 +184,9 @@ export const AppRoutes = React.memo(() => {
173
184
{
174
185
path : '/exception/:status' ,
175
186
element : < AppExceptionRoute /> ,
187
+ data : {
188
+ title : ( params ) => params . status ,
189
+ } ,
176
190
} ,
177
191
{
178
192
path : '*' ,
@@ -206,13 +220,37 @@ export const AppRoutes = React.memo(() => {
206
220
return renderMatches ( matches ) ;
207
221
} ) ( ) ;
208
222
209
- const { title } = nth ( matches , - 1 ) ?. route . data ?? { } ;
210
- usePageTitle ( title ) ;
223
+ const title = ( ( ) => {
224
+ if ( matches ) {
225
+ const match = nth ( matches , - 1 ) ! ;
226
+ const { title } = match . route . data ?? { } ;
227
+ return isFunction ( title ) ? title ( match . params ) : title ;
228
+ }
229
+ return undefined ;
230
+ } ) ( ) ;
231
+ useEffect ( ( ) => {
232
+ if ( isUndefined ( title ) ) {
233
+ document . title = TITLE_CONFIG . default ;
234
+ } else {
235
+ const arr = [ title ] ;
236
+ if ( TITLE_CONFIG . prefix ) {
237
+ arr . unshift ( TITLE_CONFIG . prefix ) ;
238
+ }
239
+ if ( TITLE_CONFIG . suffix ) {
240
+ arr . push ( TITLE_CONFIG . suffix ) ;
241
+ }
242
+ document . title = arr . join ( TITLE_CONFIG . separator ?? ' - ' ) ;
243
+ }
244
+ return ( ) => {
245
+ document . title = TITLE_CONFIG . default ;
246
+ } ;
247
+ } ) ;
211
248
212
249
return (
213
250
< RouteStateContext . Provider
214
251
value = { {
215
252
matchRoutes : matches ,
253
+ title,
216
254
} }
217
255
>
218
256
{ element }
0 commit comments