react-router-dom#matchPath JavaScript Examples
The following examples show how to use
react-router-dom#matchPath.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: useMatchPath.js From rainbow-modules with MIT License | 6 votes |
useMatchPath = () => {
return (route, pathname) => {
if (isRouterV5) {
return matchPath(pathname, {
...route,
strict: route.caseSensitive,
exact: route.end,
});
}
return matchPath(route, pathname);
};
}
Example #2
Source File: serverRouter.js From Senior-FrontEnd with MIT License | 6 votes |
router.get("*", async function (req, res, next) {
let data = {}
let getData = null
routes.some(route => {
const match = matchPath(req.path, route);
if (match) {
getData = (route.component || {}).getData
}
return match
});
if (typeof getData === 'function') {
try {
data = await getData()
} catch (error) { }
}
const appString = ReactDOMServer.renderToString(
<StaticRouter
location={req.url}
context={data}
>
<App />
</StaticRouter>)
const html = ReactDOMServer.renderToStaticMarkup(<Document data={data}>
{appString}
</Document>)
res.status(200).send(html);
});
Example #3
Source File: ErrorLogsView.js From ui-data-export with Apache License 2.0 | 6 votes |
ErrorLogsViewComponent.manifest = Object.freeze({
log: {
type: 'okapi',
records: 'errorLogs',
resourceShouldRefresh: true,
path: (_q, _p, _r, _l, props) => {
const match = matchPath(props.location.pathname, {
path: '/data-export/log/:id',
exact: true,
strict: false,
});
return `data-export/logs?limit=10000&query=(jobExecutionId==${match.params.id})`;
},
},
});
Example #4
Source File: NavSection.js From Django-REST-Framework-React-BoilerPlate with MIT License | 6 votes |
export default function NavSection({ navConfig, ...other }) {
const { pathname } = useLocation();
const match = (path) => (path ? !!matchPath({ path, end: false }, pathname) : false);
return (
<Box {...other}>
<List disablePadding sx={{ p: 1 }}>
{navConfig.map((item) => (
<NavItem key={item.title} item={item} active={match} />
))}
</List>
</Box>
);
}
Example #5
Source File: NavSection.js From course-manager with MIT License | 6 votes |
export default function NavSection({ navConfig, ...other }) {
const { pathname } = useLocation();
const match = (path) => (path ? !!matchPath({ path, end: false }, pathname) : false);
return (
<Box {...other}>
<List disablePadding>
{navConfig.map((item) => (
<NavItem key={item.title} item={item} active={match} />
))}
</List>
</Box>
);
}
Example #6
Source File: Interface.js From YApi-X with MIT License | 5 votes |
render() {
const { action } = this.props.match.params;
// const activeKey = this.state.curkey;
const activeKey = action === 'api' ? 'api' : 'colOrCase';
return (
<Layout style={{ minHeight: 'calc(100vh - 156px)', marginLeft: '24px', marginTop: '24px' }}>
<Sider style={{ height: '100%' }} width={300}>
<div className="left-menu">
<Tabs type="card" className="tabs-large" activeKey={activeKey} onChange={this.onChange}>
<Tabs.TabPane tab="接口列表" key="api" />
<Tabs.TabPane tab="测试集合" key="colOrCase" />
</Tabs>
{activeKey === 'api' ? (
<InterfaceMenu
router={matchPath(this.props.location.pathname, contentRouter)}
projectId={this.props.match.params.id}
/>
) : (
<InterfaceColMenu
router={matchPath(this.props.location.pathname, contentRouter)}
projectId={this.props.match.params.id}
/>
)}
</div>
</Sider>
<Layout>
<Content
style={{
height: '100%',
margin: '0 24px 0 16px',
overflow: 'initial',
backgroundColor: '#fff'
}}
>
<div className="right-content">
<Switch>
<Route exact path="/project/:id/interface/:action" component={InterfaceRoute} />
<Route {...contentRouter} component={InterfaceRoute} />
</Switch>
</div>
</Content>
</Layout>
</Layout>
);
}
Example #7
Source File: index.js From asblocks with GNU General Public License v3.0 | 5 votes |
export function DocumentOpen( { onOpen } ) {
const history = useHistory();
const inputRef = useRef();
const [ hasError, setHasError ] = useState( false );
const submit = ( event ) => {
event.preventDefault();
const link = inputRef.current.value;
try {
const url = new URL( link );
const pathname =
url.pathname === '/'
? url.hash.substring( 1, url.hash.indexOf( '#key=' ) )
: url.pathname;
const stringKey = link.substring( link.indexOf( '#key=' ) + 5 );
if ( link ) {
const matchRead = matchPath( pathname, {
path: '/read/:id',
exact: true,
strict: false,
} );
const matchWrite = matchPath( pathname, {
path: '/write/:id/:ownerKey',
exact: true,
strict: false,
} );
if ( matchWrite ) {
history.push(
`/write/${ matchWrite.params.id }/${ matchWrite.params.ownerKey }#key=` +
stringKey
);
onOpen();
return;
} else if ( matchRead ) {
history.push(
`/read/${ matchRead.params.id }#key=` + stringKey
);
onOpen();
return;
}
}
} catch ( error ) {}
setHasError( true );
};
return (
<form onSubmit={ submit }>
{ hasError && (
<Notice status="error">This link can not be opened.</Notice>
) }
<TextControl
ref={ inputRef }
label="Link"
placeholder="https://"
onChange={ () => setHasError( false ) }
/>
<Button isPrimary type="submit">
Open
</Button>
</form>
);
}
Example #8
Source File: Sidebar.jsx From fluentui-starter with MIT License | 5 votes |
function findRoute(pathname) {
const current = findNode(routes, (route) => {
const match = matchPath(pathname, route);
return match?.isExact;
});
const paths = current ? getParents(current) : [];
return { current, paths };
}
Example #9
Source File: UI.js From tutorial with MIT License | 5 votes |
export function Link({
className = "",
inactiveClassName = "",
activeClassName = "",
to,
exact = false,
children,
activeFor = [],
}) {
let location = useLocation();
let isActive;
if (activeFor.length > 0) {
isActive = activeFor.find((matcher) => {
return matchPath(location.pathname, {
path: matcher.path,
exact: matcher.exact,
});
});
// isActive = matchPath(location.path, { path: to.split("?")[0] });
} else {
let match = matchPath(location.pathname, { path: to.split("?")[0] });
isActive = match && (exact ? match.isExact : true);
}
// let urlToMatch = activeFor || to.split("?")[0];
// let match = useRouteMatch(urlToMatch);
// if (activeFor.length > 0) {
// isActive = match;
// } else {
// isActive = match && (exact ? match.isExact : true);
// }
let classes = `${className} ${
isActive ? activeClassName : inactiveClassName
}`;
return (
<ReactRouterLink className={classes} to={to} exact={exact ? 1 : 0}>
{children}
</ReactRouterLink>
);
}
Example #10
Source File: PictureGallery.js From 1km.co.il with MIT License | 5 votes |
function PictureGallery({ protestId }) {
const history = useHistory();
const store = useStore();
const route = matchPath(history.location.pathname, {
path: '/protest/:id/gallery/:date',
});
const galleryDate = route?.params.date;
const [pictures, setPictures] = useState([]);
const [picturesFetchState, setPicturesFetchState] = useState(false);
const getPictures = async () => {
const pictureList = await getPicturesForEvent({ protestId });
setPictures(pictureList);
setPicturesFetchState(true);
};
useEffect(() => {
getPictures();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const handleDateClick = (date) => {
history.push(`${history.location.pathname}/${date}`);
};
const picArr = galleryDate ? getPicturesForDate(pictures, galleryDate) : getGalleryThumbnails(pictures);
if (picturesFetchState && !picArr.length && galleryDate) {
const paths = history.location.pathname.split('/');
paths.pop();
history.push(paths.join('/'));
}
return (
<>
<SectionContainer>
<SectionTitle>{galleryDate ? `תמונות מ${dateToDayOfWeekAndDate(galleryDate)}` : 'גלריית תמונות'}</SectionTitle>
{pictures.length > 0 && (
<>
{galleryDate
? picArr.map((picture) => <ImageThumbnail src={picture.imageUrl} />)
: picArr.map((picture) => (
<ImageDateSection
src={picture.imageUrl}
date={picture.eventDate}
onClick={() => handleDateClick(picture.eventDate)}
/>
))}
</>
)}
<EditButton
onClick={async () => {
store.userStore.setUserProtestById(protestId);
history.push(
store.userStore.user
? `/upload-image?returnUrl=${history.location.pathname}`
: `/sign-up?returnUrl=/upload-image?returnUrl=${history.location.pathname}`
);
}}
>
הוספת תמונה לגלרייה
</EditButton>
</SectionContainer>
</>
);
}
Example #11
Source File: Profile.js From telar-cli with MIT License | 5 votes |
Profile = props => {
const { className, ...rest } = props;
const { pathname } = props.history.location;
const matchFunction = matchPath(pathname, {
path: '/:user',
strict: true,
});
const classes = useStyles();
const users = {
'de-amir': {
name: 'Amirhossein Movahedi',
avatar: '/images/avatars/amir.JPG',
bio: 'Distributed System Eng.'
},
'de-minhnguyen': {
name: 'Minh Tuan Nguyen',
avatar: '/images/avatars/minh.JPG',
bio: 'AI Eng.'
}
};
const user = users['de-amir']
return (
<div
{...rest}
className={clsx(classes.root, className)}
>
<Avatar
alt="Person"
className={classes.avatar}
component={RouterLink}
src={user.avatar}
to="/settings"
/>
<Typography
className={classes.name}
variant="h4"
>
{user.name}
</Typography>
<Typography variant="body2">{user.bio}</Typography>
</div>
);
}
Example #12
Source File: Sidebar.js From telar-cli with MIT License | 5 votes |
Sidebar = props => {
const { open, variant, onClose, className, ...rest } = props;
let user = ''
const { pathname } = props.history.location;
const matchFunction = matchPath(pathname, {
path: '/:user',
strict: true,
});
if(matchFunction) {
user = matchFunction.params.user
}
const classes = useStyles();
const pages = [
{
title: 'Installation',
href: `/setup`,
icon: <SetupIcon />
},
{
title: 'Settings',
href: `/settings`,
icon: <SettingsIcon />
}
];
return (
<Drawer
anchor="left"
classes={{ paper: classes.drawer }}
onClose={onClose}
open={open}
variant={variant}
>
<div
{...rest}
className={clsx(classes.root, className)}
>
<SidebarNav
className={classes.nav}
pages={pages}
/>
</div>
</Drawer>
);
}
Example #13
Source File: Profile.js From telar-cli with MIT License | 5 votes |
Profile = props => {
const { className, ...rest } = props;
let userLogin = ''
const { pathname } = props.history.location;
const matchFunction = matchPath(pathname, {
path: '/:user',
strict: true,
});
if(matchFunction) {
userLogin = matchFunction.params.user.toLowerCase()
}
const classes = useStyles();
const users = {
'de-amir': {
name: 'Amirhossein Movahedi',
avatar: '/images/avatars/amir.JPG',
bio: 'Distributed System Eng.'
},
'de-minhnguyen': {
name: 'Minh Tuan Nguyen',
avatar: '/images/avatars/minh.JPG',
bio: 'AI Eng.'
}
};
const user = users[userLogin]
return (
<div
{...rest}
className={clsx(classes.root, className)}
>
<Avatar
alt="Person"
className={classes.avatar}
component={RouterLink}
src={user.avatar}
to="/settings"
/>
<Typography
className={classes.name}
variant="h4"
>
{user.name}
</Typography>
<Typography variant="body2">{user.bio}</Typography>
</div>
);
}
Example #14
Source File: Sidebar.js From telar-cli with MIT License | 5 votes |
Sidebar = props => {
const { open, variant, onClose, className, ...rest } = props;
let user = ''
const { pathname } = props.history.location;
const matchFunction = matchPath(pathname, {
path: '/:user',
strict: true,
});
if(matchFunction) {
user = matchFunction.params.user
}
const classes = useStyles();
const pages = [
{
title: 'Setup',
href: `/${user}/dashboard`,
icon: <BuildIcon />
}
];
return (
<Drawer
anchor="left"
classes={{ paper: classes.drawer }}
onClose={onClose}
open={open}
variant={variant}
>
<div
{...rest}
className={clsx(classes.root, className)}
>
<Profile />
<Divider className={classes.divider} />
<SidebarNav
className={classes.nav}
pages={pages}
/>
</div>
</Drawer>
);
}
Example #15
Source File: Project.js From YApi-X with MIT License | 4 votes |
render() {
const { match, location } = this.props;
let routers = {
interface: { name: '接口', path: '/project/:id/interface/:action', component: Interface },
activity: { name: '动态', path: '/project/:id/activity', component: Activity },
data: { name: '数据管理', path: '/project/:id/data', component: ProjectData },
members: { name: '成员管理', path: '/project/:id/members', component: ProjectMember },
setting: { name: '设置', path: '/project/:id/setting', component: Setting }
};
plugin.emitHook('sub_nav', routers);
let key, defaultName;
for (key in routers) {
if (
matchPath(location.pathname, {
path: routers[key].path
}) !== null
) {
defaultName = routers[key].name;
break;
}
}
// let subnavData = [{
// name: routers.interface.name,
// path: `/project/${match.params.id}/interface/api`
// }, {
// name: routers.activity.name,
// path: `/project/${match.params.id}/activity`
// }, {
// name: routers.data.name,
// path: `/project/${match.params.id}/data`
// }, {
// name: routers.members.name,
// path: `/project/${match.params.id}/members`
// }, {
// name: routers.setting.name,
// path: `/project/${match.params.id}/setting`
// }];
let subnavData = [];
Object.keys(routers).forEach(key => {
let item = routers[key];
let value = {};
if (key === 'interface') {
value = {
name: item.name,
path: `/project/${match.params.id}/interface/api`
};
} else {
value = {
name: item.name,
path: item.path.replace(/\:id/gi, match.params.id)
};
}
subnavData.push(value);
});
if (this.props.currGroup.type === 'private') {
subnavData = subnavData.filter(item => {
return item.name != '成员管理';
});
}
if (Object.keys(this.props.curProject).length === 0) {
return <Loading visible />;
}
return (
<div>
<Subnav default={defaultName} data={subnavData} />
<Switch>
<Redirect exact from="/project/:id" to={`/project/${match.params.id}/interface/api`} />
{/* <Route path={routers.activity.path} component={Activity} />
<Route path={routers.setting.path} component={Setting} />
{this.props.currGroup.type !== 'private' ?
<Route path={routers.members.path} component={routers.members.component}/>
: null
}
<Route path={routers.data.path} component={ProjectData} /> */}
{Object.keys(routers).map(key => {
let item = routers[key];
return key === 'members' ? (
this.props.currGroup.type !== 'private' ? (
<Route path={item.path} component={item.component} key={key} />
) : null
) : (
<Route path={item.path} component={item.component} key={key} />
);
})}
</Switch>
</div>
);
}
Example #16
Source File: index.jsx From Edlib with GNU General Public License v3.0 | 4 votes |
ContentExplorerHeader = ({ onClose, getUrl }) => {
const { t } = useTranslation();
const { classes } = useStyles();
const location = useLocation();
const history = useHistory();
const { enableDoku, inMaintenanceMode } = useConfigurationContext();
const { getUserConfig } = useEdlibComponentsContext();
const isActive = (path) => {
let paths = [path];
if (Array.isArray(path)) {
paths = [...path];
}
return paths.some((path) =>
matchPath(location.pathname, {
path,
exact: false,
})
);
};
const enabledTypes =
getUserConfig('enabledResourceTypes') || Object.values(resourceEditors);
const isEditorEnabled = (type) => enabledTypes.indexOf(type) !== -1;
const editorMapping = {
[resourceEditors.H5P]: {
link: getUrl('/resources/new/contentauthor?group=h5p'),
label: t('Interaktivitet'),
},
[resourceEditors.QUESTION_SET]: {
link: getUrl('/resources/new/contentauthor?group=questionset'),
label: t('Spørsmål'),
},
// [resourceEditors.ARTICLE]: {
// link: getUrl('/resources/new/contentauthor?group=article'),
// label: t('Tekst'),
// },
// [resourceEditors.EMBED]: {
// link: '/resources/new/url',
// label: 'Link',
// },
[resourceEditors.DOKU]: {
link: getUrl('/resources/new/doku'),
label: 'EdStep',
},
};
const activatedEditorsList = Object.entries(editorMapping)
.filter(([type]) => isEditorEnabled(type))
.filter(([type]) => {
switch (type) {
case resourceEditors.DOKU:
return enableDoku;
default:
return true;
}
});
//******************************************************************************
//************ New Component ***************************************************
//******************************************************************************
const [anchorEl, setAnchorEl] = React.useState(null);
const open = Boolean(anchorEl);
const handleMenu = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const buttonClasses = (active) =>
cn(classes.headerButton, {
[classes.selectedButton]: active,
});
return (
<AppBar position="static" className={classes.appBar}>
<Toolbar className={classes.toolbar}>
<div>
<img
className={classes.logo}
src={logoUrl}
alt="edlib logo"
/>
</div>
{!inMaintenanceMode && (
<div className={classes.links}>
{activatedEditorsList.length > 1 && (
<div>
<Button
aria-controls="menu-appbar"
aria-haspopup="true"
onClick={handleMenu}
color="inherit"
startIcon={<AddCircleRounded />}
sx={{
color: isActive([
getUrl('/resources/new'),
getUrl('/link-author'),
getUrl('/doku-author'),
])
? 'secondary.main'
: 'default',
}}
className={classes.headerButton}
>
{t('Opprett innhold')}
</Button>
<Menu
id="menu-appbar"
anchorEl={anchorEl}
keepMounted
getContentAnchorEl={null}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'center',
}}
open={open}
onClose={handleClose}
>
{activatedEditorsList.map(
([type, { link, label }]) => (
<MenuItem
onClick={() => {
history.push(link);
handleClose();
}}
key={type}
>
{label}
</MenuItem>
)
)}
</Menu>
</div>
)}
{activatedEditorsList.length === 1 && (
<div>
<Button
onClick={() => {
history.push(
activatedEditorsList[0][1].link
);
handleClose();
}}
color="inherit"
startIcon={<AddCircleRounded />}
sx={{
color: isActive(
activatedEditorsList[0][1].link
)
? 'secondary.main'
: 'default',
}}
className={classes.headerButton}
>
{t('Opprett innhold')}
</Button>
</div>
)}
<div>
<Button
onClick={() => {
history.push(getUrl('/shared-content'));
handleClose();
}}
color="inherit"
startIcon={<ShoppingCart />}
sx={{
color: isActive(getUrl('/shared-content'))
? 'secondary.main'
: 'default',
}}
className={classes.headerButton}
>
{t('Delt innhold')}
</Button>
</div>
<div>
<Button
onClick={() => {
history.push(getUrl('/my-content'));
handleClose();
}}
color="inherit"
startIcon={<Home />}
sx={{
color: isActive(getUrl('/my-content'))
? 'secondary.main'
: 'default',
}}
className={classes.headerButton}
>
{t('Mitt innhold')}
</Button>
</div>
</div>
)}
{onClose ? (
<div className={classes.close}>
<Close onClick={onClose} />
</div>
) : (
<div> </div>
)}
</Toolbar>
</AppBar>
);
}
Example #17
Source File: Sidebar.jsx From Edlib with GNU General Public License v3.0 | 4 votes |
Sidebar = () => {
const classes = useStyles();
const history = useHistory();
const location = useLocation();
const [currentlyExpandedName, setCurrentlyExpandedName] =
React.useState(null);
React.useEffect(() => {
setCurrentlyExpandedName(null);
}, [location]);
const links = [
{ name: 'Dashboard', to: '/dashboard', icon: <Dashboard /> },
{ name: 'Content Author', to: '/content-author', icon: <Settings /> },
{
name: 'Settings',
to: '/settings',
icon: <Settings />,
subLinks: [
{
name: 'External applications',
to: '/external-applications',
},
],
},
{
name: 'Monitoring',
to: '/monitoring',
icon: <LocalOffer />,
subLinks: [{ name: 'Status of services', to: '/system-status' }],
},
{
name: 'Jobs',
to: '/jobs',
icon: <LocalOffer />,
subLinks: [
{ name: 'Resources', to: '/resources' },
{ name: 'Auth migration', to: '/auth-migration' },
],
},
{
name: 'Analytics',
to: '/analytics',
icon: <Assessment />,
subLinks: [{ name: 'Dashboard', to: '/dashboard' }],
},
];
return (
<List dense>
{links.map(({ name, icon, to, subLinks }) => {
const isInPath = !!matchPath(location.pathname, {
path: to,
strict: false,
});
const isExpanded = isInPath || currentlyExpandedName === name;
if (subLinks) {
return (
<React.Fragment key={name}>
<ListItem
button
selected={isInPath}
onClick={() => {
setCurrentlyExpandedName(
currentlyExpandedName === name
? null
: name
);
}}
>
{icon && <ListItemIcon>{icon}</ListItemIcon>}
<ListItemText
primary={name}
primaryTypographyProps={{
className: classes.parentItem,
}}
inset={!icon}
/>
{isExpanded ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse
in={isExpanded}
timeout="auto"
unmountOnExit
>
<List component="div" disablePadding dense>
{subLinks.map((subLink) => {
const subTo = to + subLink.to;
const isInSubPath = !!matchPath(
location.pathname,
{
path: subTo,
strict: false,
}
);
return (
<ListItem
key={subLink.name}
button
onClick={() =>
history.push(subTo)
}
selected={isInSubPath}
>
<ListItemText
primary={subLink.name}
inset
/>
</ListItem>
);
})}
</List>
</Collapse>
</React.Fragment>
);
}
return (
<ListItem
key={name}
button
selected={isInPath}
onClick={() => history.push(to)}
>
{icon && <ListItemIcon>{icon}</ListItemIcon>}
<ListItemText
primary={name}
primaryTypographyProps={{
className: classes.parentItem,
}}
inset={!icon}
/>
</ListItem>
);
})}
</List>
);
}
Example #18
Source File: load-routes.js From crate with MIT License | 4 votes |
export default function (app) {
console.info('SETUP - Load routes..')
// Store (new store for each request)
const store = createStore(
rootReducer,
applyMiddleware(thunk)
)
// Match any Route
app.get('*', (request, response) => {
// Check for auth
if (request.cookies.auth) {
const auth = JSON.parse(request.cookies.auth)
if (auth && auth.token !== '' && auth.user) {
store.dispatch(setUser(auth.token, auth.user))
}
}
// HTTP status code
let status = 200
const matches = Object.values(routes).reduce((matches, route) => {
const match = matchPath(request.url, typeof route.path === 'function' ? route.path() : route.path, route)
if (match && match.isExact) {
matches.push({
route,
match,
promise: route.component.fetchData ? route.component.fetchData({
store,
params: match.params
}) : Promise.resolve(null)
})
}
return matches
}, [])
// No such route, send 404 status
if (matches.length === 0) {
status = 404
}
// Any AJAX calls inside components
const promises = matches.map((match) => {
return match.promise
})
// Resolve the AJAX calls and render
Promise.all(promises)
.then((...data) => {
const initialState = store.getState()
const context = {}
const appHtml = renderToString(
<Provider store={store} key="provider">
<StaticRouter context={context} location={request.url}>
<App/>
</StaticRouter>
</Provider>
)
if (context.url) {
response.redirect(context.url)
} else {
// Get Meta header tags
const helmet = Helmet.renderStatic()
const styles = flushToHTML()
const html = view(APP_URL, NODE_ENV, helmet, appHtml, styles, initialState)
// Reset the state on server
store.dispatch({
type: 'RESET'
})
// Finally send generated HTML with initial data to the client
return response.status(status).send(html)
}
})
.catch(error => {
console.error(error)
})
})
}
Example #19
Source File: server.js From module-federation-examples with MIT License | 4 votes |
export async function server(event, context) {
// const wrapped = performance.timerify(someFunction);
performance.mark(`initializeFederatedImports: start`);
await initializeFederatedImports({
s3Client,
federatedModules: federatedModules.default,
});
performance.mark(`initializeFederatedImports: end`);
const extraRouteMiddleware = (
await import('@streamed-federation/federated-middleware/extraRoute')
).default;
performance.mark(`extraRouteMiddleware: end`);
console.log('extraRouteMiddleware', extraRouteMiddleware);
performance.measure(
'initializeFederatedImports',
'initializeFederatedImports: start',
'initializeFederatedImports: end',
);
performance.measure(
'extraRouteMiddleware',
'initializeFederatedImports: end',
'extraRouteMiddleware: end',
);
performance.measure(
'Federation Timing',
'initializeFederatedImports: start',
'extraRouteMiddleware: end',
);
app.use('/federated', extraRouteMiddleware);
app.get('/*', (req, res) => {
const context = {};
const store = createStore();
store.dispatch(initializeSession());
const dataRequirements = routes
.filter(route => matchPath(req.url, route)) // filter matching paths
.map(route => route.component) // map to components
.filter(comp => comp.serverFetch) // check if components have data requirement
.map(comp => store.dispatch(comp.serverFetch())); // dispatch data requirement
Promise.all(dataRequirements).then(() => {
const jsx = (
<ReduxProvider store={store}>
<StaticRouter context={context} location={req.url}>
<Layout />
</StaticRouter>
</ReduxProvider>
);
const reactDom = ReactDomServer.renderToString(jsx);
const reduxState = store.getState();
const helmetData = Helmet.renderStatic();
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(htmlTemplate(reactDom, reduxState, helmetData));
});
});
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`));
function htmlTemplate(reactDom, reduxState, helmetData) {
return `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
${helmetData.title.toString()}
${helmetData.meta.toString()}
<title>React SSR</title>
<link rel="stylesheet" type="text/css" href="./client.css" />
</head>
<body>
<div id="app">${reactDom}</div>
<script>
window.REDUX_DATA = ${serialize(reduxState, { isJSON: true })}
</script>
<script src="./client.js"></script>
</body>
</html>
`;
}
}