pushing history according to previously selected filters from localstorage

Viewed 205

Since I'm new to React I'm trying to correctly implement routing according to previous selected filters stored in local-storage and then push them to history (with a time-out) on the start-up of the application.

Without the timeout, the app jumps around between getting the user-context/token-authentication

http://localhost:3000/#tokenid=123456789012345678901234567890

and the actual URL I'd like to route to:

http://localhost:3000/monthly?date=1629361313861&dispatcher=Srv+DE+01

Since I don't know if this is the correct approach and the fact that it 'jumps' around since the UserContext is not yet established, I would really appreciate any advice on this issue I'm experiencing.

App.tsx

import React from 'react';
import { Provider } from 'react-redux';
import { ConnectedRouter } from 'connected-react-router';
import { Switch, Route } from 'react-router-dom';
import { CssBaseline } from '@material-ui/core';
import { ToastContainer } from 'react-toastify';
import { MuiPickersUtilsProvider } from '@material-ui/pickers';
import DateFnsUtils from '@date-io/date-fns';
import 'react-toastify/dist/ReactToastify.css';

import store from './services';
import history from './utils/history';
import './i18n';

import UserContext from './modules/UserContext';
import FactBox from './modules/FactBox';
import ModalRoot from './components/ModalRoot';
import pathsConst from './const/paths';
import DailyView from './pages/DailyView';
import WeeklyView from './pages/WeeklyView';
import MonthlyView from './pages/MonthlyView';
import NotFound from './pages/404';

const App = () => (
  <Provider store={store}>
    <ConnectedRouter history={history}>
      <MuiPickersUtilsProvider utils={DateFnsUtils}>
        <CssBaseline />
        <UserContext>
          <Switch>
            <Route exact path={pathsConst.INDEX} component={DailyView} />
            <Route exact path={pathsConst.WEEKLY_VIEW} component={WeeklyView} />
            <Route exact path={pathsConst.MONTHLY_VIEW} component={MonthlyView} />
            <Route component={NotFound} />
          </Switch>

          <FactBox />
          <ModalRoot />
        </UserContext>

      </MuiPickersUtilsProvider>
    </ConnectedRouter>

    <ToastContainer
      position="bottom-center"
      autoClose={6000}
      hideProgressBar
      pauseOnHover
    />
  </Provider>
);

export default App;

reducer.ts

import { combineReducers } from 'redux';
import { connectRouter as router } from 'connected-react-router';

import history from '../utils/history';
import loading from './loading/reducer';
import modal from './modal/reducer';
import resources from './resources/reducer';
import departments from './departments/reducer';
import dispatchers from './dispatchers/reducer';
import projects from './projects/reducer';
import events from './events/reducer';
import uiSettings from './uiSettings/reducer';
import userContext from './userContext/reducer';
import holidays from './holidays/reducer';

const rootReducer = combineReducers({
  router: router(history),
  loading,
  modal,
  resources,
  departments,
  dispatchers,
  projects,
  events,
  uiSettings,
  userContext,
  holidays,
});

export default rootReducer;

/utils/history.ts

import { createBrowserHistory } from 'history';
import pathsConst from '../const/paths';

function getHistory () {
  let history = createBrowserHistory({
    basename: process.env.PUBLIC_URL,
  });
  let lastPath = '/';
  let lastQueryString = localStorage.getItem("lastQueryString");
  let lastPathTemp = localStorage.getItem("lastPath");
  let lastURL = localStorage.getItem("lastURL");
  let adalID = localStorage.getItem("adal.idtoken");
  if ( lastPathTemp !== null ) {
    if (lastPathTemp.includes('weekly')=== true) {
      lastPath = pathsConst.WEEKLY_VIEW;
    }
    else if (lastPathTemp.includes('monthly')=== true) {
      lastPath = pathsConst.MONTHLY_VIEW;
    }
    else {
      lastPath = pathsConst.INDEX;
    }
  } 

  // DBG: 
  console.log('DBG - LAST QUERY STRING:', lastQueryString);
  console.log('DBG - LAST URL:', lastURL);

  if ( lastQueryString !== null && lastPath !== null && adalID !== null  ) { 

    let lastQueryStringEdit = "?date=" + Date.now();
    // INFO: Check for additional query params
    if (lastQueryString.indexOf("&") !== -1) {
      let pos1 = lastQueryString.indexOf("&");
      let substr = lastQueryString.substring(pos1, lastQueryString.length);
      lastQueryStringEdit = "?date=" + Date.now() + substr;
    } 

      setTimeout(function() {
      console.log('DBG - PUSHING.............................');
      history.push({
      pathname: lastPath,
      search: lastQueryStringEdit
      });
      }, 2000);

    return history;

  }
  else { // INFO: Return as is

    return history;

  }
}

const history  = getHistory();

export default history;
1 Answers

This is my way to access properties of url

//for accessing path of url
const {pathname} = useLocation();

...

//for going back to the last used url
const navigate = useNavigate(); //react router v6
navigate(-1) // to go back to last used url
navigate(-2) // go back to second last used url
navigate(-3) // so on ...

... For searching for a specific param in url, I make make a custom hook as follows and pass in the required variable name that i want to get value of

import { useLocation } from "react-router-dom";

export default function useGetParameter(name: string) {
  const { search } = useLocation();
  const query = new URLSearchParams(search);
  return query.get(name);
}
//this custom hook return the required param in url or null if it does not exist

Recommendation

I would recommend not to store values in localstorage this way because localstorage values have no expiry and you have to explicitly remove them from your browser. Make use of session storage with eg(useState, this.state, useContext, Redux etc) to store and access variable properties. However if you for any case still want to persist data on localstorage for a longer period of time then I'd recommend using other libraries that do this job for you. The benifit is that, these libraries are configured to be more binding and offer you seperation of logic. Do look in to redux persist

Related