Browser Reload: Does not get back to selected page, goes to default homepage – ReactJs

I am new in using ReactJS and learning it bit by bit. I have 3 pages: homepage, contacts and moviesDetails. When I travel through contacts or moviesDetails and hit browser’s reload, it gets me back to homepage which I do not want. I want it to stay on the same page which I am in.

If I am in contacts page, and hit browser’s reload, I want it to stay on contacts page. I do not want it to go to homepage.

I don’t know how to store the opened page’s path in localStorage. I need help here as I cannot figure out where I am going wrong.

Following is App.js code.

import React, { Component } from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import Homepage from "./homepage/Homepage";
import Contacts from "./contacts/Contacts";
import PrivateRoute from "./private-route/PrivateRoute";
import MoviesDetails from "./MoviesDetails/MoviesDetails";

class App extends Component {
  render() {
    return (
        <Router>
          <div className="App">
            <Switch>
              <PrivateRoute exact path="/homepage" component={Homepage} />
              <PrivateRoute exact path="/contacts" component={Contacts} />
              <PrivateRoute exact path="/moviesDetails" component={MoviesDetails} />
            </Switch>
          </div>
        </Router>
    );
  }
}
export default App;

Following is contacts.js code: (All respective components are being imported)

import React, { Component } from "react";
import { connect } from "react-redux";
import Container from '@material-ui/core/Container';
import { changeHeaderName} from '../../actions/homepageActions';    

class contacts extends Component {    
  constructor() {
    super();
    this.state = {
      data:"",
      value: 0,
      date: "",
      errorList: {}
    };
  }    
  componentDidMount() {
    this.props.header("Contacts");
  }
  render() {
    const { classes } = this.props;
    return (
      <Container>
        <TabPanel value={this.state.value}>
            <Grid container
              justify="flex-start"
              alignItems="center"
            >
              <Grid xs={6}>
                <Typography>
                  (Names here)
                </Typography>
              </Grid>
            </Grid>
        
              <Grid xs={3}>
                <Typography>
                  Contacts
                </Typography>
              </Grid>
              <Grid xs={5}>
                <Typography>
                  (All the contacts are listed here)
                </Typography>
              </Grid>
        </TabPanel>
      </Container>
    );
  }
}

const mapStateToProps = state => {
  return {mainUser: state.auth.mainUser}
};
export default connect(mapStateToProps, {header})(configurations);

Following is store.js code:

import { createStore, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import rootReducer from "./reducers";

const initialState = {};

const store = createStore(
  rootReducer,
  initialState,
  compose(
    applyMiddleware(thunk),
    (b&&a()) ||compose)
);

export default store;

And store exported above is been used in index.js file.

Given the above code, I do not want my loaded page go back to the homepage. I want to stay on the same page. Browser reload gets me back to “/homepage” instead of “/contacts”. Browser reload gets me back to “/homepage” instead of “/moviesDetails”.

I am not using any hooks here. So I don’t want my code to be in hooks. Just a simple react.js code.


EDIT NO: 1

Following is my PrivateRoute.js code

import React from "react";
import { Route, Redirect } from "react-router-dom";
import { connect } from "react-redux";
import PropTypes from "prop-types";
const PrivateRoute = ({component: Component, authentic, ...rest}) => (

    <Route 
        {...rest}
        render={ props => 
            authentic.isAuthenticated === true ? (
                    <div>
                        <Component {...props} />
                    </div>
            ) : (
                <Redirect to="/" />
            )
        }
    />
);

PrivateRoute.propTypes = {
    authentic: PropTypes.object.isRequired
};
  
const mapStateToProps = state => ({
    authentic: state.auth
});
  
export default connect(mapStateToProps)(PrivateRoute);

EDIT NO: 2

Following is redux store provider : (this is in index.js file)

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import App from './components/App';
import store from "./store";

ReactDOM.render(
    <Provider store={store}>
        <App />
    </Provider>
, document.getElementById('root'));

EDIT NO: 3

Following is MoviesDetails component

import React, { Component } from "react";
import Container from '@material-ui/core/Container';
import { connect } from "react-redux";
import Table from '@material-ui/core/Table';
import TableCell from '@material-ui/core/TableCell';
import TableHead from '@material-ui/core/TableHead';
import TableRow from '@material-ui/core/TableRow';
import TableBody from '@material-ui/core/TableBody';
import TableContainer from '@material-ui/core/TableContainer';
import { moviesList } from "./actions/moviesActions";

class MoviesDetails extends Component {
  constructor() {
    super();
    this.state = {
      skip: 0,
      limit: 10,
      pageNumber: 0,
      value: '',
      nameMovie:"",
      genre:"",
      ratings:"",
      numberOfSongs:"",
      releaseDate:"",     
    };
  }

  componentDidMount() {this.fetchRecords();}

  fetchRecords=async()=>{
    let payload ={
      nameMovie:this.state.nameMovie,
      genre:this.state.genre,
      ratings:this.state.ratings,
      numberOfSongs :this.state.numberOfSongs ,
      releaseDate : this.state.releaseDate,
      skip : this.state.limit * this.state.pageNumber,
      limit: this.state.limit,
    }
   await  this.props.moviesList(payload);
  }

  render() {
    const { classes } = this.props;
    return (    
      <div>
        <div  />
        <Container >
          <TableContainer>
            <Table>
              <TableHead>
                <TableRow>
                  <TableCell>Movie Name</TableCell>
                  <TableCell>Genre</TableCell>
                  <TableCell>Song Count</TableCell>
                  <TableCell>Ratings</TableCell>
                  <TableCell>Release Date</TableCell>
                </TableRow>
              </TableHead>
              <TableBody>
                {this.props.movies.moviesList.map((movie, index) => {
                  return (
                    <TableRow >
                      <TableCell>
                        {nameMovie}
                      </TableCell>
                      <TableCell>{genre}</TableCell>
                      <TableCell>{numberOfSongs}</TableCell>
                      <TableCell>{ratings}</TableCell>                          
                      <TableCell>{releaseDate}</TableCell>                          
                    </TableRow>
                  )
                })}
              </TableBody>                  
            </Table>
          </TableContainer>
        </Container>
      </div>
    );
  }
}

const mapStateToProps = state => {
  return {
    movie: state.movie,
    adim: state.auth.admin,
  }
};

export default connect(mapStateToProps, {moviesList })(MoviesDetails);

I handle my moviesDetails tab like this:

handleMovies = (e) => { e.preventDefault(); 
this.props.history.push("/moviesDetails"); }

Answer

You should persist your redux state to local storage when it updates, and initialize your store from local storage when app loads.

Minimal Redux Store Persistence Example:

Create a “middle” component to handle persisting state updates to localStorage.

import React, { useEffect } from 'react';
import { useSelector } from 'react-redux];

const StorePersister = ({ children }) => {
  const state = useSelector(state => state);
  useEffect(() => {
    localStorage.setItem('myState', JSON.stringify(state));
  }, [state]);

  return children;
};

index – wrap the App component with the store persister.

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import App from './components/App';
import StorePersister from './components/StorePersister';
import store from "./store";

ReactDOM.render(
  <Provider store={store}>
    <StorePersister>
      <App />
    </StorePersister>
  </Provider>,
  document.getElementById('root')
);

Initialize state from local storage. If there is no “myState” key or the parsing returns null then the empty object ({}) will be used as a fallback.

import { createStore, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import rootReducer from "./reducers";

const initialState = JSON.parse(localStorage.getItem('myState')) || {};

const store = createStore(
  rootReducer,
  initialState,
  compose(
    applyMiddleware(thunk),
    (b&&a()) || compose
  )
);

export default store;

There is also a redux-persist package out there that offers a bit of customization for what gets persisted to and initialized from the persistence.