diff --git a/package.json b/package.json
index 3e0f991ced78fba35d959afa4e5c01f474c885b4..3a1f316cd2b55712c557b34a8bc871cf8ba98ec6 100644
--- a/package.json
+++ b/package.json
@@ -32,7 +32,6 @@
     "@mui/material": "^5.3.0",
     "@mui/styles": "^5.3.0",
     "@nosferatu500/react-sortable-tree": "^3.0.5",
-    "@shakacode/recompose": "^0.30.3",
     "@turf/buffer": "^6.3.0",
     "apexcharts": "^3.33.0",
     "axios": "^0.25.0",
diff --git a/src/client/components/SemanticPortal.stories.js b/src/client/components/SemanticPortal.stories.js
index 8ef64797c6060e6c6108bbb77d2aa2973dacaf1d..b3b5ea76953b9509de95458f5ec5c6d0f90807d9 100644
--- a/src/client/components/SemanticPortal.stories.js
+++ b/src/client/components/SemanticPortal.stories.js
@@ -17,7 +17,6 @@ export const basic = () => {
   // const location = useLocation()
   // const screenSize = 'lg'
   // const rootUrlWithLang = ''
-  // const routeProps = { location }
   return (
     <SemanticPortal />
   )
diff --git a/src/client/components/facet_results/FacetResults.js b/src/client/components/facet_results/FacetResults.js
index b1fe8e6e1301873722c5107015d24230fa22e935..6d81f144a6c95c1c4097c479fc015fdd24856dfd 100644
--- a/src/client/components/facet_results/FacetResults.js
+++ b/src/client/components/facet_results/FacetResults.js
@@ -14,7 +14,6 @@ const FacetResults = props => {
   return (
     <>
       <PerspectiveTabs
-        routeProps={props.routeProps}
         tabs={perspective.tabs}
         screenSize={props.screenSize}
         layoutConfig={props.layoutConfig}
@@ -170,10 +169,6 @@ FacetResults.propTypes = {
    * Redux action for showing an error
    */
   updateFacetOption: PropTypes.func.isRequired,
-  /**
-   * Routing information from React Router.
-   */
-  routeProps: PropTypes.object.isRequired,
   /**
    * Perspective config.
    */
diff --git a/src/client/components/facet_results/FacetedSearchPerspective.js b/src/client/components/facet_results/FacetedSearchPerspective.js
index 086a8fccb60dd5b24f14d92c9673af394db49fbb..f21bfe66872c04e9d2a2770e52c23bfd28a05dd0 100644
--- a/src/client/components/facet_results/FacetedSearchPerspective.js
+++ b/src/client/components/facet_results/FacetedSearchPerspective.js
@@ -9,7 +9,7 @@ const FacetedSearchPerspective = props => {
   const {
     portalConfig, layoutConfig, perspective, perspectiveState, facetState,
     facetStateConstrainSelf, screenSize, rootUrl, apexChartsConfig, networkConfig,
-    leafletConfig, routeProps
+    leafletConfig
   } = props
   const { facetedSearchHeaderExpanded } = perspectiveState
   return (
@@ -150,7 +150,6 @@ const FacetedSearchPerspective = props => {
             updateMapBounds={props.updateMapBounds}
             sortResults={props.sortResults}
             showError={props.showError}
-            routeProps={routeProps}
             perspective={perspective}
             animationValue={props.animationValue}
             animateMap={props.animateMap}
diff --git a/src/client/components/facet_results/FederatedResults.js b/src/client/components/facet_results/FederatedResults.js
index 65b5968fadf872ce524db23e9ba8ea2c23242fe9..2d5bbf829595130fd68c79838ebf95f4823ba7d1 100644
--- a/src/client/components/facet_results/FederatedResults.js
+++ b/src/client/components/facet_results/FederatedResults.js
@@ -22,7 +22,6 @@ const FederatedResults = props => {
   return (
     <>
       <PerspectiveTabs
-        routeProps={props.routeProps}
         tabs={perspective.tabs}
         screenSize={props.screenSize}
         layoutConfig={layoutConfig}
@@ -31,108 +30,95 @@ const FederatedResults = props => {
         exact path={`${rootUrl}/${perspectiveID}/${searchMode}`}
         render={() => <Redirect to={`${rootUrl}/${perspectiveID}/${searchMode}/table`} />}
       />
-      <Route
-        path={`${rootUrl}/${perspectiveID}/${searchMode}/table`}
-        render={() =>
-          <VirtualizedTable
-            portalConfig={portalConfig}
-            list={Immutable.List(props.clientFSResults)}
-            clientFSState={props.clientFSState}
-            clientFSSortResults={props.clientFSSortResults}
-            perspectiveID={perspectiveID}
-            layoutConfig={layoutConfig}
-          />}
-      />
-      <Route
-        path={`${rootUrl}/${perspectiveID}/${searchMode}/map_clusters`}
-        render={() =>
-          <LeafletMap
-            portalConfig={portalConfig}
-            center={mapClusters.center}
-            zoom={mapClusters.zoom}
-            results={props.clientFSResults}
-            leafletMapState={props.leafletMapState}
-            resultClass='mapClusters'
-            pageType='clientFSResults'
-            mapMode='cluster'
-            createPopUpContent={props.leafletConfig.createPopUpContentNameSampo}
-            fetchResults={props.fetchResults}
-            fetchGeoJSONLayers={props.fetchGeoJSONLayers}
-            clearGeoJSONLayers={props.clearGeoJSONLayers}
-            fetchByURI={props.fetchByURI}
-            fetching={false}
-            showInstanceCountInClusters={false}
-            updateFacetOption={props.updateFacetOption}
-            showError={props.showError}
-            showExternalLayers
-            layerControlExpanded={layerControlExpanded}
-            layerConfigs={props.leafletConfig.layerConfigs}
-            updateMapBounds={props.updateMapBounds}
-            layoutConfig={layoutConfig}
-          />}
-      />
-      <Route
-        path={`${rootUrl}/${perspectiveID}/${searchMode}/map_markers`}
-        render={() => {
-          if (props.clientFSResults.length > 500) {
-            return <ResultInfo message={intl.get('leafletMap.tooManyResults')} />
-          } else {
-            return (
-              <LeafletMap
-                portalConfig={portalConfig}
-                center={mapMarkers.center}
-                zoom={mapMarkers.zoom}
-                results={props.clientFSResults}
-                leafletMapState={props.leafletMapState}
-                resultClass='mapMarkers'
-                pageType='clientFSResults'
-                mapMode='marker'
-                createPopUpContent={props.leafletConfig.createPopUpContentNameSampo}
-                fetchResults={props.fetchResults}
-                fetchGeoJSONLayers={props.fetchGeoJSONLayers}
-                clearGeoJSONLayers={props.clearGeoJSONLayers}
-                fetchByURI={props.fetchByURI}
-                fetching={false}
-                showInstanceCountInClusters={false}
-                updateFacetOption={props.updateFacetOption}
-                showError={props.showError}
-                showExternalLayers
-                layerControlExpanded={layerControlExpanded}
-                layerConfigs={props.leafletConfig.layerConfigs}
-                updateMapBounds={props.updateMapBounds}
-                layoutConfig={layoutConfig}
-              />
+      <Route path={`${rootUrl}/${perspectiveID}/${searchMode}/table`}>
+        <VirtualizedTable
+          portalConfig={portalConfig}
+          list={Immutable.List(props.clientFSResults)}
+          clientFSState={props.clientFSState}
+          clientFSSortResults={props.clientFSSortResults}
+          perspectiveID={perspectiveID}
+          layoutConfig={layoutConfig}
+        />
+      </Route>
+      <Route path={`${rootUrl}/${perspectiveID}/${searchMode}/map_clusters`}>
+        <LeafletMap
+          portalConfig={portalConfig}
+          center={mapClusters.center}
+          zoom={mapClusters.zoom}
+          results={props.clientFSResults}
+          leafletMapState={props.leafletMapState}
+          resultClass='mapClusters'
+          pageType='clientFSResults'
+          mapMode='cluster'
+          createPopUpContent={props.leafletConfig.createPopUpContentNameSampo}
+          fetchResults={props.fetchResults}
+          fetchGeoJSONLayers={props.fetchGeoJSONLayers}
+          clearGeoJSONLayers={props.clearGeoJSONLayers}
+          fetchByURI={props.fetchByURI}
+          fetching={false}
+          showInstanceCountInClusters={false}
+          updateFacetOption={props.updateFacetOption}
+          showError={props.showError}
+          showExternalLayers
+          layerControlExpanded={layerControlExpanded}
+          layerConfigs={props.leafletConfig.layerConfigs}
+          updateMapBounds={props.updateMapBounds}
+          layoutConfig={layoutConfig}
+        />
+      </Route>
+      <Route path={`${rootUrl}/${perspectiveID}/${searchMode}/map_markers`}>
+        {props.clientFSResults.length < 500
+          ? (
+            <LeafletMap
+              portalConfig={portalConfig}
+              center={mapMarkers.center}
+              zoom={mapMarkers.zoom}
+              results={props.clientFSResults}
+              leafletMapState={props.leafletMapState}
+              resultClass='mapMarkers'
+              pageType='clientFSResults'
+              mapMode='marker'
+              createPopUpContent={props.leafletConfig.createPopUpContentNameSampo}
+              fetchResults={props.fetchResults}
+              fetchGeoJSONLayers={props.fetchGeoJSONLayers}
+              clearGeoJSONLayers={props.clearGeoJSONLayers}
+              fetchByURI={props.fetchByURI}
+              fetching={false}
+              showInstanceCountInClusters={false}
+              updateFacetOption={props.updateFacetOption}
+              showError={props.showError}
+              showExternalLayers
+              layerControlExpanded={layerControlExpanded}
+              layerConfigs={props.leafletConfig.layerConfigs}
+              updateMapBounds={props.updateMapBounds}
+              layoutConfig={layoutConfig}
+            />
             )
-          }
-        }}
-      />
-      <Route
-        path={`${rootUrl}/${perspectiveID}/${searchMode}/statistics`}
-        render={() =>
-          <Pie
-            portalConfig={portalConfig}
-            data={props.clientFSResults}
-            groupBy={props.clientFSState.groupBy}
-            groupByLabel={props.clientFSState.groupByLabel}
-            query={props.clientFSState.query}
-            layoutConfig={layoutConfig}
-          />}
-      />
-      <Route
-        path={`${rootUrl}/${perspectiveID}/${searchMode}/download`}
-        render={() =>
-          <CSVButton
-            results={props.clientFSResults}
-            layoutConfig={layoutConfig}
-            portalConfig={portalConfig}
-          />}
-      />
+          : <ResultInfo message={intl.get('leafletMap.tooManyResults')} />}
+      </Route>
+      <Route path={`${rootUrl}/${perspectiveID}/${searchMode}/statistics`}>
+        <Pie
+          portalConfig={portalConfig}
+          data={props.clientFSResults}
+          groupBy={props.clientFSState.groupBy}
+          groupByLabel={props.clientFSState.groupByLabel}
+          query={props.clientFSState.query}
+          layoutConfig={layoutConfig}
+        />
+      </Route>
+      <Route path={`${rootUrl}/${perspectiveID}/${searchMode}/download`}>
+        <CSVButton
+          results={props.clientFSResults}
+          layoutConfig={layoutConfig}
+          portalConfig={portalConfig}
+        />
+      </Route>
+
     </>
   )
 }
 
 FederatedResults.propTypes = {
-  routeProps: PropTypes.object.isRequired,
   perspective: PropTypes.object.isRequired,
   screenSize: PropTypes.string.isRequired,
   clientFSState: PropTypes.object.isRequired,
diff --git a/src/client/components/facet_results/FederatedSearchPerspective.js b/src/client/components/facet_results/FederatedSearchPerspective.js
index 0674aea0d009637b00a7c0f615364cbbe40950ae..5589a6d99b58b97c8f4198d13a785546950d3518 100644
--- a/src/client/components/facet_results/FederatedSearchPerspective.js
+++ b/src/client/components/facet_results/FederatedSearchPerspective.js
@@ -8,7 +8,7 @@ const FederatedSearchPerspective = props => {
   const {
     portalConfig, layoutConfig, perspective,
     screenSize, rootUrl, apexChartsConfig, networkConfig,
-    leafletConfig, routeProps
+    leafletConfig
   } = props
 
   const MainClientFS = lazy(() => import(`../../components/perspectives/${portalConfig.portalID}/MainClientFS`))
@@ -103,7 +103,6 @@ const FederatedSearchPerspective = props => {
             portalConfig={portalConfig}
             layoutConfig={layoutConfig}
             perspective={perspective}
-            routeProps={routeProps}
             screenSize={screenSize}
             clientFSState={props.clientFSState}
             clientFSResults={props.clientFSResults}
diff --git a/src/client/components/facet_results/ReactVirtualizedTable.js b/src/client/components/facet_results/ReactVirtualizedTable.js
index 2593116627baafc754a3a335ddecc0be2e763f63..cd80f2de8ae1cc0c3cfd0f3b88ee23a2c15a68d8 100644
--- a/src/client/components/facet_results/ReactVirtualizedTable.js
+++ b/src/client/components/facet_results/ReactVirtualizedTable.js
@@ -187,7 +187,7 @@ MuiVirtualizedTable.propTypes = {
 const VirtualizedTable = withStyles(styles)(MuiVirtualizedTable)
 
 const rootStyle = {
-  height: 'calc(100% - 80px)',
+  height: 'calc(100% - 58px)',
   fontFamily: 'Roboto'
 }
 
@@ -200,7 +200,7 @@ const tableContainer = {
 
 const progressContainerStyle = {
   width: '100%',
-  height: 'calc(100% - 80px)',
+  height: 'calc(100% - 58px)',
   display: 'flex',
   alignItems: 'center',
   justifyContent: 'center'
diff --git a/src/client/components/facet_results/ResultClassRoute.js b/src/client/components/facet_results/ResultClassRoute.js
index 200b090d977fede203058994f5810cae0ddca65f..8e0cadc4efd8c6007444a3333fccd6b59fd540c5 100644
--- a/src/client/components/facet_results/ResultClassRoute.js
+++ b/src/client/components/facet_results/ResultClassRoute.js
@@ -1,6 +1,6 @@
 import React, { lazy } from 'react'
 import intl from 'react-intl-universal'
-import { Route } from 'react-router-dom'
+import { Route, useLocation } from 'react-router-dom'
 import { has } from 'lodash'
 // import LineChartSotasurmat from '../perspectives/sotasurmat/LineChartSotasurmat'
 const ResultTable = lazy(() => import('./ResultTable'))
@@ -52,40 +52,32 @@ const ResultClassRoute = props => {
   switch (component) {
     case 'ResultTable':
       routeComponent = (
-        <Route
-          path={path}
-          render={routeProps =>
-            <ResultTable
-              portalConfig={portalConfig}
-              perspectiveConfig={perspective}
-              data={perspectiveState}
-              facetUpdateID={facetState.facetUpdateID}
-              resultClass={resultClass}
-              facetClass={facetClass}
-              fetchPaginatedResults={props.fetchPaginatedResults}
-              updatePage={props.updatePage}
-              updateRowsPerPage={props.updateRowsPerPage}
-              sortResults={props.sortResults}
-              routeProps={routeProps}
-              rootUrl={rootUrl}
-              layoutConfig={layoutConfig}
-            />}
+        <ResultTable
+          portalConfig={portalConfig}
+          perspectiveConfig={perspective}
+          data={perspectiveState}
+          facetUpdateID={facetState.facetUpdateID}
+          resultClass={resultClass}
+          facetClass={facetClass}
+          fetchPaginatedResults={props.fetchPaginatedResults}
+          updatePage={props.updatePage}
+          updateRowsPerPage={props.updateRowsPerPage}
+          sortResults={props.sortResults}
+          rootUrl={rootUrl}
+          layoutConfig={layoutConfig}
+          location={useLocation()}
         />
       )
       break
     case 'ReactVirtualizedList':
       routeComponent = (
-        <Route
-          path={path}
-          render={routeProps =>
-            <ReactVirtualizedList
-              resultClass={resultClass}
-              facetClass={facetClass}
-              fetchResults={props.fetchResults}
-              perspectiveState={perspectiveState}
-              facetUpdateID={facetState.facetUpdateID}
-              layoutConfig={layoutConfig}
-            />}
+        <ReactVirtualizedList
+          resultClass={resultClass}
+          facetClass={facetClass}
+          fetchResults={props.fetchResults}
+          perspectiveState={perspectiveState}
+          facetUpdateID={facetState.facetUpdateID}
+          layoutConfig={layoutConfig}
         />
       )
       break
@@ -116,12 +108,7 @@ const ResultClassRoute = props => {
           data: perspectiveState.instanceTableData
         }
       }
-      routeComponent = (
-        <Route
-          path={path}
-          render={routeProps => <InstancePageTable {...instanceTableProps} />}
-        />
-      )
+      routeComponent = <InstancePageTable {...instanceTableProps} />
       break
     }
     case 'LeafletMap': {
@@ -183,13 +170,7 @@ const ResultClassRoute = props => {
       if (pageType === 'instancePage') {
         leafletProps.uri = perspectiveState.instanceTableData.id
       }
-      routeComponent = (
-        <Route
-          path={path}
-          render={() =>
-            <LeafletMap {...leafletProps} />}
-        />
-      )
+      routeComponent = <LeafletMap {...leafletProps} />
       break
     }
     case 'Deck': {
@@ -238,12 +219,7 @@ const ResultClassRoute = props => {
           instanceVariable
         }
       }
-      routeComponent = (
-        <Route
-          path={path}
-          render={() => <Deck {...deckProps} />}
-        />
-      )
+      routeComponent = <Deck {...deckProps} />
       break
     }
     case 'ApexCharts': {
@@ -267,13 +243,7 @@ const ResultClassRoute = props => {
         facetUpdateID: facetState ? facetState.facetUpdateID : null,
         fetchData: props.fetchResults
       }
-      routeComponent = (
-        <Route
-          path={path}
-          render={() =>
-            <ApexCharts {...apexProps} />}
-        />
-      )
+      routeComponent = <ApexCharts {...apexProps} />
       break
     }
     // case 'LineChartSotasurmat': {
@@ -282,16 +252,9 @@ const ResultClassRoute = props => {
     //     facetUpdateID: facetState.facetUpdateID,
     //     fetchResults: props.fetchResults,
     //     updatePage: props.updatePage,
-    //     routeProps: props.routeProps,
     //     resultCount: perspectiveState.resultCount
     //   }
-    //   routeComponent = (
-    //     <Route
-    //       path={path}
-    //       render={() =>
-    //         <LineChartSotasurmat {...lineChartProps} />}
-    //     />
-    //   )
+    //   routeComponent = <LineChartSotasurmat {...lineChartProps} />
     //   break
     // }
     case 'Network': {
@@ -332,13 +295,7 @@ const ResultClassRoute = props => {
       if (pageType === 'instancePage') {
         networkProps.uri = perspectiveState.instanceTableData.id
       }
-      routeComponent = (
-        <Route
-          path={path}
-          render={() =>
-            <Network {...networkProps} />}
-        />
-      )
+      routeComponent = <Network {...networkProps} />
       break
     }
     case 'VideoPage': {
@@ -351,17 +308,10 @@ const ResultClassRoute = props => {
         perspectiveState,
         properties: getVisibleRows(perspectiveState),
         localID: props.localID,
-        routeProps: props.routeProps,
         videoPlayerState: props.videoPlayerState,
         updateVideoPlayerTime: props.updateVideoPlayerTime
       }
-      routeComponent = (
-        <Route
-          path={path}
-          render={() =>
-            <VideoPage {...videoPageProps} />}
-        />
-      )
+      routeComponent = <VideoPage {...videoPageProps} />
       break
     }
     case 'TemporalMap': {
@@ -378,61 +328,41 @@ const ResultClassRoute = props => {
         animateMap: props.animateMap,
         facetUpdateID: facetState.facetUpdateID
       }
-      routeComponent = (
-        <Route
-          path={path}
-          render={() =>
-            <TemporalMap {...temporalMapProps} />}
-        />
-      )
+      routeComponent = <TemporalMap {...temporalMapProps} />
       break
     }
     case 'WordCloud': {
       const wordCloudProps = {
         data: perspectiveState.instanceTableData[resultClassConfig.wordCloudProperty]
       }
-      routeComponent = (
-        <Route
-          path={path}
-          render={() =>
-            <WordCloud {...wordCloudProps} />}
-        />
-      )
+      routeComponent = <WordCloud {...wordCloudProps} />
       break
     }
     case 'Export': {
       const { pageType = 'facetResults' } = resultClassConfig
       const exportResultClass = resultClassConfig.resultClass
       routeComponent = (
-        <Route
-          path={path}
-          render={routeProps =>
-            <Export
-              portalConfig={portalConfig}
-              data={perspectiveState}
-              resultClass={exportResultClass}
-              facetClass={facetClass}
-              pageType={pageType}
-              fetchPaginatedResults={props.fetchPaginatedResults}
-              updatePage={props.updatePage}
-              layoutConfig={props.layoutConfig}
-            />}
+        <Export
+          portalConfig={portalConfig}
+          data={perspectiveState}
+          resultClass={exportResultClass}
+          facetClass={facetClass}
+          pageType={pageType}
+          fetchPaginatedResults={props.fetchPaginatedResults}
+          updatePage={props.updatePage}
+          layoutConfig={props.layoutConfig}
         />
       )
       break
     }
     case 'ExportCSV': {
       routeComponent = (
-        <Route
-          path={path}
-          render={routeProps =>
-            <ExportCSV
-              resultClass={resultClass}
-              facetClass={facetClass}
-              facetUpdateID={facetState.facetUpdateID}
-              facets={facetState.facets}
-              layoutConfig={layoutConfig}
-            />}
+        <ExportCSV
+          resultClass={resultClass}
+          facetClass={facetClass}
+          facetUpdateID={facetState.facetUpdateID}
+          facets={facetState.facets}
+          layoutConfig={layoutConfig}
         />
       )
       break
@@ -441,7 +371,11 @@ const ResultClassRoute = props => {
       routeComponent = <></>
       break
   }
-  return routeComponent
+  return (
+    <Route path={path}>
+      {routeComponent}
+    </Route>
+  )
 }
 
 export default ResultClassRoute
diff --git a/src/client/components/facet_results/ResultTable.js b/src/client/components/facet_results/ResultTable.js
index 5ba30fdf2a5ca2ba225dee0e07c16ad0edfaac4f..e4cf39b1e32571a16cad1712080d1180ca4e77ac 100644
--- a/src/client/components/facet_results/ResultTable.js
+++ b/src/client/components/facet_results/ResultTable.js
@@ -85,10 +85,10 @@ class ResultTable extends React.Component {
     let page
 
     // first check if page was given as url parameter
-    if (this.props.routeProps.location.search === '') {
+    if (this.props.location.search === '') {
       page = this.props.data.page === -1 ? 0 : this.props.data.page
     } else {
-      const qs = this.props.routeProps.location.search.replace('?', '')
+      const qs = this.props.location.search.replace('?', '')
       page = parseInt(querystring.parse(qs).page)
     }
 
@@ -126,7 +126,7 @@ class ResultTable extends React.Component {
 
     // handle browser's back button
     window.onpopstate = () => {
-      const qs = this.props.routeProps.location.search.replace('?', '')
+      const qs = this.props.location.search.replace('?', '')
       const newPage = parseInt(querystring.parse(qs).page)
       if (newPage !== this.props.data.page) {
         this.props.updatePage(this.props.resultClass, newPage)
@@ -338,7 +338,6 @@ class ResultTable extends React.Component {
                   onSortBy={this.handleSortBy}
                   sortBy={sortBy}
                   sortDirection={sortDirection}
-                  routeProps={this.props.routeProps}
                 />
                 <TableBody>
                   {paginatedResults.map(row => this.rowRenderer(row))}
@@ -361,7 +360,7 @@ ResultTable.propTypes = {
   sortResults: PropTypes.func.isRequired,
   updatePage: PropTypes.func.isRequired,
   updateRowsPerPage: PropTypes.func.isRequired,
-  routeProps: PropTypes.object.isRequired,
+  location: PropTypes.object.isRequired,
   rootUrl: PropTypes.string.isRequired
 }
 
diff --git a/src/client/components/facet_results/ResultTable.stories.js b/src/client/components/facet_results/ResultTable.stories.js
index 16acce75d89f770d1ec3e7cf0a6109c15e94ebfb..cb9a94766ab6ca2a42339d3e47ae52c8f0cf3690 100644
--- a/src/client/components/facet_results/ResultTable.stories.js
+++ b/src/client/components/facet_results/ResultTable.stories.js
@@ -11,9 +11,6 @@ export default {
 export const basic = () => {
   const facetResults = useSelector(state => state.perspective1)
   const location = useLocation()
-  const routeProps = {
-    location
-  }
   return (
     <div style={{ width: '100%', height: '100%' }}>
       <ResultTable
@@ -25,7 +22,7 @@ export const basic = () => {
         updatePage={() => null}
         updateRowsPerPage={() => null}
         sortResults={() => null}
-        routeProps={routeProps}
+        location={location}
         rootUrl=''
       />
     </div>
diff --git a/src/client/components/facet_results/ResultTableHead.js b/src/client/components/facet_results/ResultTableHead.js
index 2d9f2a939d98a9045cc4d8172e6d1181b4b64aab..69bec665cbe84cf961a305dd96061596838d078d 100644
--- a/src/client/components/facet_results/ResultTableHead.js
+++ b/src/client/components/facet_results/ResultTableHead.js
@@ -98,8 +98,7 @@ ResultTableHead.propTypes = {
   columns: PropTypes.array.isRequired,
   onSortBy: PropTypes.func.isRequired,
   sortBy: PropTypes.string,
-  sortDirection: PropTypes.string,
-  routeProps: PropTypes.object.isRequired
+  sortDirection: PropTypes.string
 }
 
 export default withStyles(styles)(ResultTableHead)
diff --git a/src/client/components/main_layout/FullTextSearch.js b/src/client/components/main_layout/FullTextSearch.js
index 937b62bb7319866f84444a89a9e6a3efb479a4ea..c0a851e417de8caba2f0f34df5c54dc65dc27cf6 100644
--- a/src/client/components/main_layout/FullTextSearch.js
+++ b/src/client/components/main_layout/FullTextSearch.js
@@ -1,29 +1,35 @@
 import React from 'react'
 import PropTypes from 'prop-types'
 import { Route, Redirect } from 'react-router-dom'
-import makeStyles from '@mui/styles/makeStyles'
+import Box from '@mui/material/Box'
 import PerspectiveTabs from './PerspectiveTabs'
 import ReactVirtualizedTable from '../facet_results/ReactVirtualizedTable'
 import CalendarViewDayIcon from '@mui/icons-material/CalendarViewDay'
-
-const useStyles = makeStyles(theme => ({
-  root: props => ({
-    marginTop: theme.spacing(0.5),
-    height: `calc(100% - ${props.layoutConfig.tabHeight - 18}px)`
-  })
-}))
+import { getSpacing } from '../../helpers/helpers'
 
 /**
  * A component for displaying full text search results.
  */
 const FullTextSearch = props => {
   const { rootUrl, layoutConfig, screenSize } = props
-  const classes = useStyles(props)
   const perspectiveUrl = `${rootUrl}/full-text-search`
   return (
-    <div className={classes.root}>
+    <Box
+      sx={theme => ({
+        margin: theme.spacing(0.5),
+        [theme.breakpoints.up(layoutConfig.hundredPercentHeightBreakPoint)]: {
+          height: `calc(100% - ${layoutConfig.topBar.reducedHeight +
+              getSpacing(theme, 1)
+              }px)`
+        },
+        [theme.breakpoints.up(layoutConfig.reducedHeightBreakpoint)]: {
+          height: `calc(100% - ${layoutConfig.topBar.defaultHeight +
+              getSpacing(theme, 1)
+              }px)`
+        }
+      })}
+    >
       <PerspectiveTabs
-        routeProps={props.routeProps}
         tabs={[{
           id: 'table',
           label: 'table',
@@ -33,30 +39,23 @@ const FullTextSearch = props => {
         screenSize={screenSize}
         layoutConfig={layoutConfig}
       />
-      <Route
-        exact path={perspectiveUrl}
-        render={() => <Redirect to={`${perspectiveUrl}/table`} />}
-      />
-      <Route
-        path={`${perspectiveUrl}/table`}
-        render={() => {
-          return (
-            <ReactVirtualizedTable
-              fullTextSearch={props.fullTextSearch}
-              resultClass={props.resultClass}
-              sortFullTextResults={props.sortFullTextResults}
-              layoutConfig={props.layoutConfig}
-            />
-          )
-        }}
-      />
-    </div>
+      <Route exact path={perspectiveUrl}>
+        <Redirect to={`${perspectiveUrl}/table`} />
+      </Route>
+      <Route path={`${perspectiveUrl}/table`}>
+        <ReactVirtualizedTable
+          fullTextSearch={props.fullTextSearch}
+          resultClass={props.resultClass}
+          sortFullTextResults={props.sortFullTextResults}
+          layoutConfig={props.layoutConfig}
+        />
+      </Route>
+    </Box>
   )
 }
 
 FullTextSearch.propTypes = {
   fullTextSearch: PropTypes.object.isRequired,
-  routeProps: PropTypes.object.isRequired,
   screenSize: PropTypes.string.isRequired,
   rootUrl: PropTypes.string.isRequired
 }
diff --git a/src/client/components/main_layout/InstancePage.js b/src/client/components/main_layout/InstancePage.js
index b7ff28ea6744ae4a11f49c624e0525f4ee16a066..1e84ee0f8dc9e49c5ccfa6e248e1c3f8ff59c853 100644
--- a/src/client/components/main_layout/InstancePage.js
+++ b/src/client/components/main_layout/InstancePage.js
@@ -45,8 +45,8 @@ class InstancePage extends React.Component {
 
   componentDidUpdate = prevProps => {
     // handle the case when the TABLE tab was not originally active
-    const prevPathname = prevProps.routeProps.location.pathname
-    const currentPathname = this.props.routeProps.location.pathname
+    const prevPathname = prevProps.location.pathname
+    const currentPathname = this.props.location.pathname
     if (!this.hasTableData() && prevPathname !== currentPathname && currentPathname.endsWith('table')) {
       this.fetchTableData()
     }
@@ -59,7 +59,7 @@ class InstancePage extends React.Component {
 
   getLocalID = () => {
     return getLocalIDFromAppLocation({
-      location: this.props.routeProps.location,
+      location: this.props.location,
       perspectiveConfig: this.props.perspectiveConfig
     })
   }
@@ -112,7 +112,6 @@ class InstancePage extends React.Component {
     return (
       <div className={classes.root}>
         <PerspectiveTabs
-          routeProps={this.props.routeProps}
           tabs={perspectiveConfig.instancePageTabs}
           screenSize={screenSize}
           layoutConfig={layoutConfig}
@@ -230,7 +229,7 @@ InstancePage.propTypes = {
   /**
     * Routing information from React Router.
     */
-  routeProps: PropTypes.object.isRequired,
+  location: PropTypes.object.isRequired,
   /**
     * Perspective config.
     */
diff --git a/src/client/components/main_layout/InstancePagePerspective.js b/src/client/components/main_layout/InstancePagePerspective.js
index 43691cdb3124e7316896870638acb4a179efddb0..3f91c1d9b3ecb4244f417788ed07af7187c1fa8a 100644
--- a/src/client/components/main_layout/InstancePagePerspective.js
+++ b/src/client/components/main_layout/InstancePagePerspective.js
@@ -3,12 +3,13 @@ import InfoHeader from '../main_layout/InfoHeader'
 import InstancePage from './InstancePage'
 import Grid from '@mui/material/Grid'
 import { getSpacing } from '../../helpers/helpers'
+import { useLocation } from 'react-router-dom'
 
 const InstancePagePerspective = props => {
   const {
     portalConfig, layoutConfig, perspective, perspectiveState,
     screenSize, rootUrl, apexChartsConfig, networkConfig,
-    leafletConfig, routeProps
+    leafletConfig
   } = props
   const { instancePageHeaderExpanded } = perspectiveState
   return (
@@ -95,7 +96,6 @@ const InstancePagePerspective = props => {
             updateMapBounds={props.updateMapBounds}
             sortResults={props.sortResults}
             showError={props.showError}
-            routeProps={routeProps}
             perspective={perspective}
             animationValue={props.animationValue}
             animateMap={props.animateMap}
@@ -106,6 +106,7 @@ const InstancePagePerspective = props => {
             apexChartsConfig={apexChartsConfig}
             leafletConfig={leafletConfig}
             networkConfig={networkConfig}
+            location={useLocation()}
           />
         </Grid>
       </Grid>
diff --git a/src/client/components/main_layout/PerspectiveTabs.js b/src/client/components/main_layout/PerspectiveTabs.js
index 869078fc8ecc21d0787a29ede04f36b3ee8d9b9a..d5f7374e694991d3e052a67e7ea28a8324ebf677 100644
--- a/src/client/components/main_layout/PerspectiveTabs.js
+++ b/src/client/components/main_layout/PerspectiveTabs.js
@@ -1,104 +1,86 @@
-import React from 'react'
+import React, { useState, useEffect } from 'react'
 import PropTypes from 'prop-types'
+import { Link, useLocation } from 'react-router-dom'
 import Tabs from '@mui/material/Tabs'
 import Tab from '@mui/material/Tab'
-import { Link } from 'react-router-dom'
 import Paper from '@mui/material/Paper'
 import intl from 'react-intl-universal'
 
+// helper function for converting a tab path into tab index value
+const pathnameToTabValue = (location, tabs) => {
+  const activeID = location.pathname.split('/').pop()
+  let value = 0
+  tabs.forEach(tab => {
+    if (tab.id === activeID) {
+      value = tab.value
+    }
+  })
+  return value
+}
+
 /**
- * A component for generating view tabs for a faceted search perspective or an entity landing page.
+ * A component for generating view tabs for a faceted search perspective or an instance page.
  */
-class PerspectiveTabs extends React.Component {
-  constructor (props) {
-    super(props)
-    this.state = {
-      value: this.pathnameToValue(this.props.routeProps.location.pathname)
-    }
-  }
+const PerspectiveTabs = props => {
+  const { tabs, layoutConfig } = props
+  const variant = tabs.length > 3 ? 'scrollable' : 'fullWidth'
+  // const largeScreen = screenSize === 'xl'
+  // const scrollButtons = tabs.length > 3 ? 'auto' : 'on'
+  const location = useLocation()
 
-  componentDidUpdate = prevProps => {
-    const newPath = this.props.routeProps.location.pathname
-    const oldPath = prevProps.routeProps.location.pathname
-    if (newPath !== oldPath) {
-      this.setState({ value: this.pathnameToValue(newPath) })
-    }
+  const [value, setValue] = useState(pathnameToTabValue(location, tabs))
 
-    // Fix tabs indicator not showing on first load, not needed any more?
-    // https://stackoverflow.com/a/61205108
-    // const evt = document.createEvent('UIEvents')
-    // evt.initUIEvent('resize', true, false, window, 0)
-    // window.dispatchEvent(evt)
-  }
+  useEffect(() => {
+    setValue(pathnameToTabValue(location, tabs))
+  }, [location])
 
-  pathnameToValue = pathname => {
-    const activeID = pathname.split('/').pop()
-    let value = 0
-    this.props.tabs.forEach(tab => {
-      if (tab.id === activeID) {
-        value = tab.value
-      }
-    })
-    return value
+  const handleChange = (event, newValue) => {
+    setValue(newValue)
   }
 
-  handleChange = (event, value) => {
-    this.setState({ value })
-  };
-
-  render () {
-    const { tabs } = this.props
-    const { value } = this.state
-    // const largeScreen = screenSize === 'xl'
-    const variant = tabs.length > 3 ? 'scrollable' : 'fullWidth'
-    // const scrollButtons = tabs.length > 3 ? 'auto' : 'on'
-    return (
-      <Paper
-        sx={theme => ({
-          flexGrow: 1,
-          borderBottomLeftRadius: 0,
-          borderBottomRightRadius: 0
-        })}
+  return (
+    <Paper
+      sx={theme => ({
+        flexGrow: 1,
+        borderBottomLeftRadius: 0,
+        borderBottomRightRadius: 0
+      })}
+    >
+      <Tabs
+        value={value}
+        onChange={handleChange}
+        indicatorColor='secondary'
+        textColor='secondary'
+        variant={variant}
       >
-        <Tabs
-          value={value}
-          onChange={this.handleChange}
-          indicatorColor='secondary'
-          textColor='secondary'
-          variant={variant}
-        >
-          {tabs.map(tab =>
-            <Tab
-              sx={theme => ({
-                paddingTop: theme.spacing(0.5),
-                paddingBottom: theme.spacing(0.5),
-                minHeight: this.props.layoutConfig.tabHeight,
-                '& .MuiSvgIcon-root': {
-                  marginBottom: theme.spacing(0.5)
-                }
-              })}
-              key={tab.value}
-              value={tab.value}
-              icon={tab.icon}
-              label={intl.get(`tabs.${tab.id}`)}
-              component={Link}
-              to={tab.id}
-              wrapped
-            />
-          )}
-        </Tabs>
-      </Paper>
-    )
-  }
+        {tabs.map(tab =>
+          <Tab
+            sx={theme => ({
+              paddingTop: theme.spacing(0.5),
+              paddingBottom: theme.spacing(0.5),
+              minHeight: layoutConfig.tabHeight,
+              '& .MuiSvgIcon-root': {
+                marginBottom: theme.spacing(0.5)
+              }
+            })}
+            key={tab.value}
+            value={tab.value}
+            icon={tab.icon}
+            label={intl.get(`tabs.${tab.id}`)}
+            component={Link}
+            to={tab.id}
+            wrapped
+          />
+        )}
+      </Tabs>
+    </Paper>
+  )
 }
 
 PerspectiveTabs.propTypes = {
-  routeProps: PropTypes.object.isRequired,
   tabs: PropTypes.array.isRequired,
   screenSize: PropTypes.string.isRequired,
   layoutConfig: PropTypes.object.isRequired
 }
 
-export const PerspectiveTabsComponent = PerspectiveTabs
-
 export default PerspectiveTabs
diff --git a/src/client/components/main_layout/PerspectiveTabs.stories.js b/src/client/components/main_layout/PerspectiveTabs.stories.js
index 619693ec9908a82d6a9f1a1ea8ed5feeb85ce1bf..9e3102bfd99d2eba3e8f7702f71fef522f711481 100644
--- a/src/client/components/main_layout/PerspectiveTabs.stories.js
+++ b/src/client/components/main_layout/PerspectiveTabs.stories.js
@@ -1,7 +1,6 @@
 import React from 'react'
 import PerspectiveTabs, { PerspectiveTabsComponent } from './PerspectiveTabs'
 import { perspectiveConfig } from '../../configs/sampo/PerspectiveConfig'
-import { useLocation } from 'react-router-dom'
 
 export default {
   component: PerspectiveTabsComponent,
@@ -10,11 +9,8 @@ export default {
 
 export const basic = () => {
   const perspective = perspectiveConfig[0]
-  const location = useLocation()
-  const routeProps = { location }
   return (
     <PerspectiveTabs
-      routeProps={routeProps}
       tabs={perspective.tabs}
       screenSize='md'
     />
diff --git a/src/client/components/main_layout/Player.js b/src/client/components/main_layout/Player.js
index d01ec655fd5774d857247f043691d7738ba80560..e8b03c69f0b63fb86c0a77b258a24724aa6b9c7d 100644
--- a/src/client/components/main_layout/Player.js
+++ b/src/client/components/main_layout/Player.js
@@ -1,5 +1,5 @@
 import React from 'react'
-import withStyles from '@mui/styles/withStyles';
+import withStyles from '@mui/styles/withStyles'
 
 const styles = theme => ({
   // https://www.w3schools.com/howto/howto_css_responsive_iframes.asp
@@ -38,7 +38,7 @@ class Player extends React.Component {
   }
 
   componentDidUpdate = prevProps => {
-    if (this.props.routeProps.location.hash !== prevProps.routeProps.location.hash) {
+    if (this.props.location.hash !== prevProps.location.hash) {
       this.seekToBasedOnHash()
     }
   }
@@ -50,7 +50,7 @@ class Player extends React.Component {
   }
 
   seekToBasedOnHash = () => {
-    const seconds = this.props.routeProps.location.hash.substring(1)
+    const seconds = this.props.location.hash.substring(1)
     // https://developers.google.com/youtube/iframe_api_reference#seekTo
     this.player.seekTo(seconds)
   }
@@ -71,7 +71,7 @@ class Player extends React.Component {
   }
 
   onPlayerReady = event => {
-    if (this.props.routeProps.location.hash === '') {
+    if (this.props.location.hash === '') {
       this.props.updateVideoPlayerTime(parseInt(this.player.getCurrentTime()))
     } else {
       this.seekToBasedOnHash()
diff --git a/src/client/components/main_layout/VideoPage.js b/src/client/components/main_layout/VideoPage.js
index 19ae3796d8015bce32d115737d3c94105fcda757..c0d9a245af16117cdca5cbafcb6bf265ee9e8cb6 100644
--- a/src/client/components/main_layout/VideoPage.js
+++ b/src/client/components/main_layout/VideoPage.js
@@ -1,5 +1,5 @@
 import React from 'react'
-import makeStyles from '@mui/styles/makeStyles';
+import makeStyles from '@mui/styles/makeStyles'
 import Paper from '@mui/material/Paper'
 import Grid from '@mui/material/Grid'
 import { Typography } from '@mui/material'
@@ -7,6 +7,7 @@ import InstancePageTable from './InstancePageTable'
 import Player from './Player'
 import VideoTableOfContents from './VideoTableOfContents'
 import { has } from 'lodash'
+import { useLocation } from 'react-router-dom'
 
 const useStyles = makeStyles(theme => ({
   root: {
@@ -111,7 +112,7 @@ const VideoPage = props => {
               <Player
                 resultClass={props.resultClass}
                 data={instanceTableData}
-                routeProps={props.routeProps}
+                location={useLocation()}
                 videoPlayerState={props.videoPlayerState}
                 updateVideoPlayerTime={props.updateVideoPlayerTime}
               />}
diff --git a/src/client/containers/SemanticPortal.js b/src/client/containers/SemanticPortal.js
index b1cd4e287f850fb8d7982cb0efdf467397c9888e..f35202027a9076036a7d241c809c4612a03ad6bf 100644
--- a/src/client/containers/SemanticPortal.js
+++ b/src/client/containers/SemanticPortal.js
@@ -3,8 +3,7 @@ import PropTypes from 'prop-types'
 import intl from 'react-intl-universal'
 import { has } from 'lodash'
 import { connect } from 'react-redux'
-import { withRouter, Route, Redirect, Switch } from 'react-router-dom'
-import { compose } from '@shakacode/recompose'
+import { Route, Redirect, Switch, useLocation } from 'react-router-dom'
 import Box from '@mui/material/Box'
 import {
   fetchResultCount,
@@ -45,7 +44,8 @@ import {
   processPortalConfig,
   createPerspectiveConfig,
   createPerspectiveConfigOnlyInfoPages,
-  getScreenSize
+  getScreenSize,
+  usePageViews
 } from '../helpers/helpers'
 import * as apexChartsConfig from '../library_configs/ApexCharts/ApexChartsConfig'
 import * as leafletConfig from '../library_configs/Leaflet/LeafletConfig'
@@ -94,10 +94,15 @@ const Footer = lazy(() => import(`../components/perspectives/${portalID}/Footer`
  */
 const SemanticPortal = props => {
   const { error } = props
+  const location = useLocation()
   const rootUrlWithLang = `${rootUrl}/${props.options.currentLocale}`
   const screenSize = getScreenSize()
   const noClientFSResults = props.clientFSState && props.clientFSState.results === null
 
+  // trigger a new “page view” event whenever a new page loads
+  usePageViews()
+
+  // set HTML title and description dynamically based on translations
   useEffect(() => {
     document.title = intl.get('html.title')
     document.documentElement.lang = props.options.currentLocale
@@ -116,10 +121,10 @@ const SemanticPortal = props => {
         }
       })}
     >
-      {/* Error messages are shown on top of the app. */}
+      {/* error messages are shown on top of the app */}
       <Message error={error} />
       <>
-        {/* No route for TopBar, because it is always visible. */}
+        {/* no route for TopBar, because it is always visible */}
         <TopBar
           rootUrl={rootUrlWithLang}
           search={props.fullTextSearch}
@@ -131,278 +136,247 @@ const SemanticPortal = props => {
           availableLocales={props.options.availableLocales}
           loadLocales={props.loadLocales}
           screenSize={screenSize}
-          location={props.location}
+          location={location}
           layoutConfig={layoutConfig}
         />
-        {/* Enforce a lang tag. */}
+        {/* enforce a lang tag */}
         <Route exact path={`${rootUrl}/`}>
           <Redirect to={rootUrlWithLang} />
         </Route>
-        {/* Create a route for portal front page. */}
-        <Route
-          exact path={`${rootUrlWithLang}/`}
-          render={() =>
-            <>
-              <Main
-                perspectives={perspectiveConfig}
-                screenSize={screenSize}
-                rootUrl={rootUrlWithLang}
-                layoutConfig={layoutConfig}
-              />
-              <Footer
-                portalConfig={portalConfig}
-                layoutConfig={layoutConfig}
-              />
-            </>}
-        />
-        {/* https://stackoverflow.com/a/41024944 */}
-        <Route
-          path={`${rootUrlWithLang}/`} render={({ location }) => {
-            if (typeof window.ga === 'function') {
-              window.ga('set', 'page', location.pathname + location.search)
-              window.ga('send', 'pageview')
-            }
-            return null
-          }}
-        />
-        {/* Create a route for full text search results. */}
-        <Route
-          path={`${rootUrlWithLang}/full-text-search`}
-          render={routeProps =>
-            <FullTextSearch
-              fullTextSearch={props.fullTextSearch}
-              resultClass='fullTextSearch'
-              sortFullTextResults={props.sortFullTextResults}
-              routeProps={routeProps}
+        {/* create a route for portal front page */}
+        <Route exact path={`${rootUrlWithLang}`}>
+          <>
+            <Main
+              perspectives={perspectiveConfig}
               screenSize={screenSize}
               rootUrl={rootUrlWithLang}
               layoutConfig={layoutConfig}
-            />}
-        />
-        {/* Create routes for faceted search perspectives and corresponding instance pages. */}
+            />
+            <Footer
+              portalConfig={portalConfig}
+              layoutConfig={layoutConfig}
+            />
+          </>
+        </Route>
+        {/* create a route for full text search results */}
+        <Route path={`${rootUrlWithLang}/full-text-search`}>
+          <FullTextSearch
+            fullTextSearch={props.fullTextSearch}
+            resultClass='fullTextSearch'
+            sortFullTextResults={props.sortFullTextResults}
+            screenSize={screenSize}
+            rootUrl={rootUrlWithLang}
+            layoutConfig={layoutConfig}
+          />
+        </Route>
+        {/* create routes for faceted search perspectives and corresponding instance pages */}
         {perspectiveConfig.map(perspective => {
           if (!has(perspective, 'externalUrl') && perspective.searchMode === 'faceted-search') {
             return (
               <React.Fragment key={perspective.id}>
-                <Route
-                  path={`${rootUrlWithLang}/${perspective.id}/faceted-search`}
-                  render={routeProps =>
-                    <FacetedSearchPerspective
+                <Route path={`${rootUrlWithLang}/${perspective.id}/faceted-search`}>
+                  <FacetedSearchPerspective
+                    portalConfig={portalConfig}
+                    perspectiveConfig={perspective}
+                    layoutConfig={layoutConfig}
+                    facetedSearchMode='serverFS'
+                    facetState={props[`${perspective.id}Facets`]}
+                    facetStateConstrainSelf={props[`${perspective.id}FacetsConstrainSelf`]}
+                    perspectiveState={props[perspective.id]}
+                    facetClass={perspective.id}
+                    resultClass={perspective.id}
+                    fetchingResultCount={props[perspective.id].fetchingResultCount}
+                    resultCount={props[perspective.id].resultCount}
+                    fetchFacet={props.fetchFacet}
+                    fetchFacetConstrainSelf={props.fetchFacetConstrainSelf}
+                    fetchResults={props.fetchResults}
+                    clearFacet={props.clearFacet}
+                    clearAllFacets={props.clearAllFacets}
+                    fetchResultCount={props.fetchResultCount}
+                    updateFacetOption={props.updateFacetOption}
+                    showError={props.showError}
+                    defaultActiveFacets={perspective.defaultActiveFacets}
+                    rootUrl={rootUrlWithLang}
+                    screenSize={screenSize}
+                    apexChartsConfig={apexChartsConfig}
+                    leafletConfig={leafletConfig}
+                    networkConfig={networkConfig}
+                    leafletMapState={props.leafletMap}
+                    fetchPaginatedResults={props.fetchPaginatedResults}
+                    fetchInstanceAnalysis={props.fetchInstanceAnalysis}
+                    fetchGeoJSONLayers={props.fetchGeoJSONLayers}
+                    fetchGeoJSONLayersBackend={props.fetchGeoJSONLayersBackend}
+                    clearGeoJSONLayers={props.clearGeoJSONLayers}
+                    fetchByURI={props.fetchByURI}
+                    updatePage={props.updatePage}
+                    updateRowsPerPage={props.updateRowsPerPage}
+                    updateMapBounds={props.updateMapBounds}
+                    updatePerspectiveHeaderExpanded={props.updatePerspectiveHeaderExpanded}
+                    sortResults={props.sortResults}
+                    perspective={perspective}
+                    animationValue={props.animationValue}
+                    animateMap={props.animateMap}
+                  />
+                </Route>
+                <Switch>
+                  <Redirect
+                    from={`/${perspective.id}/page/:id`}
+                    to={{
+                      pathname: `${rootUrlWithLang}/${perspective.id}/page/:id`,
+                      hash: location.hash
+                    }}
+                  />
+                  <Route path={`${rootUrlWithLang}/${perspective.id}/page/:id`}>
+                    <InstancePagePerspective
                       portalConfig={portalConfig}
-                      perspectiveConfig={perspective}
                       layoutConfig={layoutConfig}
-                      facetedSearchMode='serverFS'
-                      facetState={props[`${perspective.id}Facets`]}
-                      facetStateConstrainSelf={props[`${perspective.id}FacetsConstrainSelf`]}
-                      perspectiveState={props[perspective.id]}
-                      facetClass={perspective.id}
-                      resultClass={perspective.id}
-                      fetchingResultCount={props[perspective.id].fetchingResultCount}
-                      resultCount={props[perspective.id].resultCount}
-                      fetchFacet={props.fetchFacet}
-                      fetchFacetConstrainSelf={props.fetchFacetConstrainSelf}
-                      fetchResults={props.fetchResults}
-                      clearFacet={props.clearFacet}
-                      clearAllFacets={props.clearAllFacets}
-                      fetchResultCount={props.fetchResultCount}
-                      updateFacetOption={props.updateFacetOption}
-                      showError={props.showError}
-                      defaultActiveFacets={perspective.defaultActiveFacets}
-                      rootUrl={rootUrlWithLang}
-                      screenSize={screenSize}
-                      apexChartsConfig={apexChartsConfig}
-                      leafletConfig={leafletConfig}
-                      networkConfig={networkConfig}
+                      perspectiveConfig={perspective}
+                      perspectiveState={props[`${perspective.id}`]}
                       leafletMapState={props.leafletMap}
                       fetchPaginatedResults={props.fetchPaginatedResults}
+                      fetchResults={props.fetchResults}
                       fetchInstanceAnalysis={props.fetchInstanceAnalysis}
+                      fetchFacetConstrainSelf={props.fetchFacetConstrainSelf}
                       fetchGeoJSONLayers={props.fetchGeoJSONLayers}
                       fetchGeoJSONLayersBackend={props.fetchGeoJSONLayersBackend}
                       clearGeoJSONLayers={props.clearGeoJSONLayers}
                       fetchByURI={props.fetchByURI}
                       updatePage={props.updatePage}
                       updateRowsPerPage={props.updateRowsPerPage}
+                      updateFacetOption={props.updateFacetOption}
                       updateMapBounds={props.updateMapBounds}
-                      updatePerspectiveHeaderExpanded={props.updatePerspectiveHeaderExpanded}
                       sortResults={props.sortResults}
-                      routeProps={routeProps}
+                      showError={props.showError}
                       perspective={perspective}
                       animationValue={props.animationValue}
                       animateMap={props.animateMap}
-                    />}
-                />
-                <Switch>
-                  <Redirect
-                    from={`/${perspective.id}/page/:id`}
-                    to={{
-                      pathname: `${rootUrlWithLang}/${perspective.id}/page/:id`,
-                      hash: props.location.hash
-                    }}
-                  />
-                  <Route
-                    path={`${rootUrlWithLang}/${perspective.id}/page/:id`}
-                    render={routeProps =>
-                      <InstancePagePerspective
-                        portalConfig={portalConfig}
-                        layoutConfig={layoutConfig}
-                        perspectiveConfig={perspective}
-                        perspectiveState={props[`${perspective.id}`]}
-                        leafletMapState={props.leafletMap}
-                        fetchPaginatedResults={props.fetchPaginatedResults}
-                        fetchResults={props.fetchResults}
-                        fetchInstanceAnalysis={props.fetchInstanceAnalysis}
-                        fetchFacetConstrainSelf={props.fetchFacetConstrainSelf}
-                        fetchGeoJSONLayers={props.fetchGeoJSONLayers}
-                        fetchGeoJSONLayersBackend={props.fetchGeoJSONLayersBackend}
-                        clearGeoJSONLayers={props.clearGeoJSONLayers}
-                        fetchByURI={props.fetchByURI}
-                        updatePage={props.updatePage}
-                        updateRowsPerPage={props.updateRowsPerPage}
-                        updateFacetOption={props.updateFacetOption}
-                        updateMapBounds={props.updateMapBounds}
-                        sortResults={props.sortResults}
-                        showError={props.showError}
-                        routeProps={routeProps}
-                        perspective={perspective}
-                        animationValue={props.animationValue}
-                        animateMap={props.animateMap}
-                        videoPlayerState={props.videoPlayer}
-                        updateVideoPlayerTime={props.updateVideoPlayerTime}
-                        updatePerspectiveHeaderExpanded={props.updatePerspectiveHeaderExpanded}
-                        screenSize={screenSize}
-                        rootUrl={rootUrlWithLang}
-                        apexChartsConfig={apexChartsConfig}
-                        leafletConfig={leafletConfig}
-                        networkConfig={networkConfig}
-                      />}
-                  />
+                      videoPlayerState={props.videoPlayer}
+                      updateVideoPlayerTime={props.updateVideoPlayerTime}
+                      updatePerspectiveHeaderExpanded={props.updatePerspectiveHeaderExpanded}
+                      screenSize={screenSize}
+                      rootUrl={rootUrlWithLang}
+                      apexChartsConfig={apexChartsConfig}
+                      leafletConfig={leafletConfig}
+                      networkConfig={networkConfig}
+                    />
+                  </Route>
                 </Switch>
               </React.Fragment>
             )
           }
           return null
         })}
-        {/* Create routes for perspectives that have only instance pages. */}
+        {/* create routes for perspectives that have only instance pages */}
         {perspectiveConfigOnlyInfoPages.map(perspective =>
           <Switch key={perspective.id}>
             <Redirect
               from={`${rootUrl}/${perspective.id}/page/:id`}
               to={`${rootUrlWithLang}/${perspective.id}/page/:id`}
             />
-            <Route
-              path={`${rootUrlWithLang}/${perspective.id}/page/:id`}
-              render={routeProps =>
-                <InstancePagePerspective
-                  portalConfig={portalConfig}
-                  layoutConfig={layoutConfig}
-                  perspectiveConfig={perspective}
-                  perspectiveState={props[`${perspective.id}`]}
-                  leafletMapState={props.leafletMap}
-                  fetchPaginatedResults={props.fetchPaginatedResults}
-                  fetchResults={props.fetchResults}
-                  fetchInstanceAnalysis={props.fetchInstanceAnalysis}
-                  fetchFacetConstrainSelf={props.fetchFacetConstrainSelf}
-                  fetchGeoJSONLayers={props.fetchGeoJSONLayers}
-                  fetchGeoJSONLayersBackend={props.fetchGeoJSONLayersBackend}
-                  clearGeoJSONLayers={props.clearGeoJSONLayers}
-                  fetchByURI={props.fetchByURI}
-                  updatePage={props.updatePage}
-                  updateRowsPerPage={props.updateRowsPerPage}
-                  updateFacetOption={props.updateFacetOption}
-                  updateMapBounds={props.updateMapBounds}
-                  sortResults={props.sortResults}
-                  showError={props.showError}
-                  routeProps={routeProps}
-                  perspective={perspective}
-                  animationValue={props.animationValue}
-                  animateMap={props.animateMap}
-                  videoPlayerState={props.videoPlayer}
-                  updateVideoPlayerTime={props.updateVideoPlayerTime}
-                  updatePerspectiveHeaderExpanded={props.updatePerspectiveHeaderExpanded}
-                  screenSize={screenSize}
-                  rootUrl={rootUrlWithLang}
-                  apexChartsConfig={apexChartsConfig}
-                  leafletConfig={leafletConfig}
-                  networkConfig={networkConfig}
-                />}
-            />
+            <Route path={`${rootUrlWithLang}/${perspective.id}/page/:id`}>
+              <InstancePagePerspective
+                portalConfig={portalConfig}
+                layoutConfig={layoutConfig}
+                perspectiveConfig={perspective}
+                perspectiveState={props[`${perspective.id}`]}
+                leafletMapState={props.leafletMap}
+                fetchPaginatedResults={props.fetchPaginatedResults}
+                fetchResults={props.fetchResults}
+                fetchInstanceAnalysis={props.fetchInstanceAnalysis}
+                fetchFacetConstrainSelf={props.fetchFacetConstrainSelf}
+                fetchGeoJSONLayers={props.fetchGeoJSONLayers}
+                fetchGeoJSONLayersBackend={props.fetchGeoJSONLayersBackend}
+                clearGeoJSONLayers={props.clearGeoJSONLayers}
+                fetchByURI={props.fetchByURI}
+                updatePage={props.updatePage}
+                updateRowsPerPage={props.updateRowsPerPage}
+                updateFacetOption={props.updateFacetOption}
+                updateMapBounds={props.updateMapBounds}
+                sortResults={props.sortResults}
+                showError={props.showError}
+                perspective={perspective}
+                animationValue={props.animationValue}
+                animateMap={props.animateMap}
+                videoPlayerState={props.videoPlayer}
+                updateVideoPlayerTime={props.updateVideoPlayerTime}
+                updatePerspectiveHeaderExpanded={props.updatePerspectiveHeaderExpanded}
+                screenSize={screenSize}
+                rootUrl={rootUrlWithLang}
+                apexChartsConfig={apexChartsConfig}
+                leafletConfig={leafletConfig}
+                networkConfig={networkConfig}
+              />
+            </Route>
           </Switch>
         )}
-        {/* Optional: create a route for client side faceted search. */}
-        <Route
-          path={`${rootUrlWithLang}/perspective4/federated-search`}
-          render={routeProps =>
-            <FederatedSearchPerspective
-              portalConfig={portalConfig}
-              layoutConfig={layoutConfig}
-              facetedSearchMode='clientFS'
-              facetClass='perspective4'
-              resultClass='perspective4'
-              facetState={props.clientFSState}
-              clientFSFacetValues={props.clientFSFacetValues}
-              fetchingResultCount={props.clientFSState.textResultsFetching}
-              resultCount={noClientFSResults ? 0 : props.clientFSState.results.length}
-              noClientFSResults={noClientFSResults}
-              clientFSState={props.clientFSState}
-              clientFSToggleDataset={props.clientFSToggleDataset}
-              clientFSFetchResults={props.clientFSFetchResults}
-              clientFSClearResults={props.clientFSClearResults}
-              clientFSUpdateQuery={props.clientFSUpdateQuery}
-              clientFSUpdateFacet={props.clientFSUpdateFacet}
-              defaultActiveFacets={perspectiveConfig.find(p => p.id === 'perspective4').defaultActiveFacets}
-              updateMapBounds={props.updateMapBounds}
-              screenSize={screenSize}
-              showError={props.showError}
-              rootUrl={rootUrlWithLang}
-              apexChartsConfig={apexChartsConfig}
-              leafletConfig={leafletConfig}
-              networkConfig={networkConfig}
-              perspective={perspectiveConfig.find(p => p.id === 'perspective4')}
-              routeProps={routeProps}
-              clientFSResults={props.clientFSResults}
-              clientFSSortResults={props.clientFSSortResults}
-              leafletMapState={props.leafletMap}
-              fetchGeoJSONLayersBackend={props.fetchGeoJSONLayersBackend}
-              fetchGeoJSONLayers={props.fetchGeoJSONLayers}
-              clearGeoJSONLayers={props.clearGeoJSONLayers}
-            />}
-        />
-        {/* Create routes for top bar info buttons. */}
+        {/* optional: create a route for client side faceted search */}
+        <Route path={`${rootUrlWithLang}/perspective4/federated-search`}>
+          <FederatedSearchPerspective
+            portalConfig={portalConfig}
+            layoutConfig={layoutConfig}
+            facetedSearchMode='clientFS'
+            facetClass='perspective4'
+            resultClass='perspective4'
+            facetState={props.clientFSState}
+            clientFSFacetValues={props.clientFSFacetValues}
+            fetchingResultCount={props.clientFSState.textResultsFetching}
+            resultCount={noClientFSResults ? 0 : props.clientFSState.results.length}
+            noClientFSResults={noClientFSResults}
+            clientFSState={props.clientFSState}
+            clientFSToggleDataset={props.clientFSToggleDataset}
+            clientFSFetchResults={props.clientFSFetchResults}
+            clientFSClearResults={props.clientFSClearResults}
+            clientFSUpdateQuery={props.clientFSUpdateQuery}
+            clientFSUpdateFacet={props.clientFSUpdateFacet}
+            defaultActiveFacets={perspectiveConfig.find(p => p.id === 'perspective4').defaultActiveFacets}
+            updateMapBounds={props.updateMapBounds}
+            screenSize={screenSize}
+            showError={props.showError}
+            rootUrl={rootUrlWithLang}
+            apexChartsConfig={apexChartsConfig}
+            leafletConfig={leafletConfig}
+            networkConfig={networkConfig}
+            perspective={perspectiveConfig.find(p => p.id === 'perspective4')}
+            clientFSResults={props.clientFSResults}
+            clientFSSortResults={props.clientFSSortResults}
+            leafletMapState={props.leafletMap}
+            fetchGeoJSONLayersBackend={props.fetchGeoJSONLayersBackend}
+            fetchGeoJSONLayers={props.fetchGeoJSONLayers}
+            clearGeoJSONLayers={props.clearGeoJSONLayers}
+          />
+        </Route>
+        {/* create routes for top bar info buttons */}
         {!layoutConfig.topBar.externalAboutPage &&
-          <Route
-            path={`${rootUrlWithLang}/about`}
-            render={() =>
-              <TextPage layoutConfig={layoutConfig}>
-                {intl.getHTML('aboutThePortalPartOne')}
-                {knowledgeGraphMetadataConfig.showTable &&
-                  <KnowledgeGraphMetadataTable
-                    portalConfig={portalConfig}
-                    layoutConfig={layoutConfig}
-                    perspectiveID={knowledgeGraphMetadataConfig.perspective}
-                    resultClass='knowledgeGraphMetadata'
-                    fetchKnowledgeGraphMetadata={props.fetchKnowledgeGraphMetadata}
-                    knowledgeGraphMetadata={props[knowledgeGraphMetadataConfig.perspective]
-                      ? props[knowledgeGraphMetadataConfig.perspective].knowledgeGraphMetadata
-                      : null}
-                  />}
-                {intl.getHTML('aboutThePortalPartTwo')}
-              </TextPage>}
-          />}
-        {/* Create a route for instructions page */}
+          <Route path={`${rootUrlWithLang}/about`}>
+            <TextPage layoutConfig={layoutConfig}>
+              {intl.getHTML('aboutThePortalPartOne')}
+              {knowledgeGraphMetadataConfig.showTable &&
+                <KnowledgeGraphMetadataTable
+                  portalConfig={portalConfig}
+                  layoutConfig={layoutConfig}
+                  perspectiveID={knowledgeGraphMetadataConfig.perspective}
+                  resultClass='knowledgeGraphMetadata'
+                  fetchKnowledgeGraphMetadata={props.fetchKnowledgeGraphMetadata}
+                  knowledgeGraphMetadata={props[knowledgeGraphMetadataConfig.perspective]
+                    ? props[knowledgeGraphMetadataConfig.perspective].knowledgeGraphMetadata
+                    : null}
+                />}
+              {intl.getHTML('aboutThePortalPartTwo')}
+            </TextPage>
+          </Route>}
+        {/* create a route for instructions page */}
         {!layoutConfig.topBar.externalInstructions &&
-          <Route
-            path={`${rootUrlWithLang}/instructions`}
-            render={() =>
-              <TextPage layoutConfig={layoutConfig}>
-                {intl.getHTML('instructions')}
-              </TextPage>}
-          />}
+          <Route path={`${rootUrlWithLang}/instructions`}>
+            <TextPage layoutConfig={layoutConfig}>
+              {intl.getHTML('instructions')}
+            </TextPage>
+          </Route>}
       </>
     </Box>
   )
 }
 
-// State: connect the Redux store and React components.
+// state: connect the Redux store and React components
 const mapStateToProps = state => {
   const stateToProps = {}
   perspectiveConfig.forEach(perspective => {
@@ -434,7 +408,7 @@ const mapStateToProps = state => {
   return stateToProps
 }
 
-// Actions: connect the Redux store and React components.
+// actions: connect the Redux store and React components
 const mapDispatchToProps = ({
   fetchResultCount,
   fetchPaginatedResults,
@@ -598,10 +572,7 @@ SemanticPortal.propTypes = {
   clientFSUpdateFacet: PropTypes.func
 }
 
-export default compose(
-  withRouter,
-  connect(
-    mapStateToProps,
-    mapDispatchToProps
-  )
+export default connect(
+  mapStateToProps,
+  mapDispatchToProps
 )(SemanticPortal)
diff --git a/src/client/helpers/helpers.js b/src/client/helpers/helpers.js
index 89d734dfc9d43fd4afa697189cb87ce69dcc455c..1f615609392f86619400dcefc3947816019475d4 100644
--- a/src/client/helpers/helpers.js
+++ b/src/client/helpers/helpers.js
@@ -1,4 +1,5 @@
-import React from 'react'
+import React, { useEffect } from 'react'
+import { useLocation } from 'react-router-dom'
 import querystring from 'querystring'
 import { has, sortBy } from 'lodash'
 import intl from 'react-intl-universal'
@@ -307,3 +308,14 @@ export const getScreenSize = () => {
   if (xlScreen) { screenSize = 'xl' }
   return screenSize
 }
+
+// https://v5.reactrouter.com/web/api/Hooks/uselocation
+export const usePageViews = () => {
+  const location = useLocation()
+  useEffect(() => {
+    if (typeof window.ga === 'function') {
+      console.log(window.ga)
+      window.ga.send(['pageview', location.pathname])
+    }
+  }, [location])
+}