Home > Net >  My React app doesn't reload the page when hitting the back button
My React app doesn't reload the page when hitting the back button

Time:10-24

I have a React App(v18.2.0) with react-router-dom(v5.2.0). The navigation works correctly but when I click the browser's Back button the URL changes but no state is updated and the page doesn't get re-rendered. I tried so many different things and none of them works.

A case for example, is when I call the CreateUserComponent on the ListUserComponent, then if i want to go backwards using the browser back button the URL changes to the List component but the screen keeps the same.

So my question is how can I get the page to load when the user goes back, because i do not know what i am doing wrong?

App.js

import React from 'react';
import './App.css';
import {BrowserRouter as Router, Route, Switch} from 'react-router-dom';
import ListUserComponent from './components/ListUserComponent';
import HeaderComponent from './components/HeaderComponent';
import FooterComponent from './components/FooterComponent';
import CreateUserComponent from './components/CreateUserComponent';
import UpdateUserComponent from './components/UpdateUserComponent';
import ViewUserComponent from './components/ViewUserComponent';

function App() {
  return (
    <div>
      <Router forceRefresh={true}>
          <HeaderComponent />
            <div className="container">
              <Switch>
                <Route path = "/" exact component = {ListUserComponent}></Route>
                <Route path = "/users" component = {ListUserComponent}></Route>
                <Route path = "/add-user/:id" component = {CreateUserComponent}></Route>
                <Route path = "/view-user/:id" component = {ViewUserComponent}></Route>
              </Switch>
            </div>  
          <FooterComponent />
      </Router>
    </div>
  );
}

export default App;

CreateUserComponent.jsx

import React, { Component } from 'react';
import UserService from '../services/UserService';

class CreateUserComponent extends Component {
    constructor(props) {
        super(props)

        this.state = {
            //Step 2
            id: this.props.match.params.id,
            firstName: '',
            lastName: '',
            email: '',
            password: ''
        }

        this.changeFirstNameHandler = this.changeFirstNameHandler.bind(this);
        this.changeLastNameHandler = this.changeLastNameHandler.bind(this);
        this.saveOrUpdateUser = this.saveOrUpdateUser.bind(this);
    }

    //Step 3        
    componentDidMount() {
        //Step 4
        if (this.state.id === 'add') {
            return
        } else {
            UserService.getUserById(this.state.id).then((res) => {
                let user = res.data;
                this.setState({
                    firstName: user.firstName,
                    lastName: user.lastName,
                    emailId: user.emailId
                });
            });
        }
    }

    saveOrUpdateUser = (e) => {
        e.preventDefault();
        let user = { firstName: this.state.firstName, lastName: this.state.lastName, email: this.state.email, password: this.state.password };
        console.log('user => '   JSON.stringify(user));

        //Step 5
        if (this.state.id === 'add') {
            UserService.createUser(user).then(res => {
                this.props.history.push('/users');
            });
        } else {
            UserService.updateUser(user, this.state.id).then(res => {
                this.props.history.push('/users');
            });
        }
    }

    changeFirstNameHandler = (event) => {
        this.setState({ firstName: event.target.value });
    }

    changeLastNameHandler = (event) => {
        this.setState({ lastName: event.target.value });
    }

    changeEmailHandler = (event) => {
        this.setState({ email: event.target.value });
    }

    changePasswordHandler = (event) => {
        this.setState({ password: event.target.value });
    }

    cancel() {
        this.props.history.push('/users');
    }

    getTitle() {
        if (this.state.id === 'add') {
            return <h3 className="text-center">Modificar Usuario</h3>
        } else {
            return <h3 className="text-center">Añadir Usuario</h3>
        }
    }


    render() {
        return (
            <div>
                <div className="container">
                    <div className="row">
                        <div className="card col-md-6 offset-md-3 offset-md-3">
                            {
                                this.getTitle()
                            }
                            <div className="card-body">
                                <form>
                                    <div className="form-group">
                                        <label>Nombre: </label>
                                        <input placeholder="Nombre" name="firstName" className="form-control" value={this.state.firstName} onChange={this.changeFirstNameHandler} />
                                    </div>
                                    <div className="form-group">
                                        <label> Apellidos: </label>
                                        <input placeholder="Apellidos" name="lastName" className="form-control" value={this.state.lastName} onChange={this.changeLastNameHandler} />
                                    </div>
                                    <div className="form-group">
                                        <label> Email: </label>
                                        <input placeholder="Email" name="email" className="form-control" value={this.state.email} onChange={this.changeEmailHandler} />
                                    </div>
                                    <div className="form-group">
                                        <label> Contraseña: </label>
                                        <input placeholder="Contraseña" name="password" className="form-control" value={this.state.password} onChange={this.changePasswordHandler} />
                                    </div>
                                    <button className="btn btn-success" onClick={this.saveOrUpdateUser}>Guardar</button>
                                    <button className="btn btn-danger" onClick={this.cancel.bind(this)} style={{ marginLeft: "10px" }}>Cancelar</button>
                                </form>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        )
    }
}

export default CreateUserComponent;

package.json

{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "axios": "^1.1.3",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^5.2.0",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

CodePudding user response:

Your components work well on my machine since I've added preventDefault() to the cancel function.

App.jsx

import React from 'react';
import './App.css';
import {BrowserRouter as Router, Route, Switch} from 'react-router-dom';
import ListUserComponent from './components/ListUserComponent';
import HeaderComponent from './components/HeaderComponent';
import FooterComponent from './components/FooterComponent';
import CreateUserComponent from './components/CreateUserComponent';
import UpdateUserComponent from './components/UpdateUserComponent';
import ViewUserComponent from './components/ViewUserComponent';

function App() {
  return (
    <div>
      <Router> {/* removed forceRefresh */}
          <HeaderComponent />
            <div className="container">
              <Switch>
                <Route path = "/" exact component = {ListUserComponent}></Route>
                <Route path = "/users" component = {ListUserComponent}></Route>
                <Route path = "/add-user/:id" component = {CreateUserComponent}></Route>
                <Route path = "/view-user/:id" component = {ViewUserComponent}></Route>
              </Switch>
            </div>  
          <FooterComponent />
      </Router>
    </div>
  );
}

export default App;

CreateUserComponent.jsx

import React, { Component } from 'react';
// import UserService from '../services/UserService';

class CreateUserComponent extends Component {
    constructor(props) {
        super(props)

        this.state = {
            //Step 2
            id: this.props.match.params.id,
            firstName: '',
            lastName: '',
            email: '',
            password: ''
        }

        this.changeFirstNameHandler = this.changeFirstNameHandler.bind(this);
        this.changeLastNameHandler = this.changeLastNameHandler.bind(this);
        this.saveOrUpdateUser = this.saveOrUpdateUser.bind(this);
    }

    //Step 3        
    componentDidMount() {
        //Step 4
        if (this.state.id === 'add') {
            return
        } else {
            // UserService.getUserById(this.state.id).then((res) => {
            //     let user = res.data;
            //     this.setState({
            //         firstName: user.firstName,
            //         lastName: user.lastName,
            //         emailId: user.emailId
            //     });
            // });
        }
    }

    saveOrUpdateUser = (e) => {
        e.preventDefault();
        let user = { firstName: this.state.firstName, lastName: this.state.lastName, email: this.state.email, password: this.state.password };
        console.log('user => '   JSON.stringify(user));

        //Step 5
        if (this.state.id === 'add') {
            // UserService.createUser(user).then(res => {
            //     this.props.history.push('/users');
            // });
        } else {
            // UserService.updateUser(user, this.state.id).then(res => {
            //     this.props.history.push('/users');
            // });
        }
    }

    changeFirstNameHandler = (event) => {
        this.setState({ firstName: event.target.value });
    }

    changeLastNameHandler = (event) => {
        this.setState({ lastName: event.target.value });
    }

    changeEmailHandler = (event) => {
        this.setState({ email: event.target.value });
    }

    changePasswordHandler = (event) => {
        this.setState({ password: event.target.value });
    }

    cancel(event) {
        event.preventDefault(); // added preventDefault()
        this.props.history.push('/users');
    }

    getTitle() {
        if (this.state.id === 'add') {
            return <h3 className="text-center">Modificar Usuario</h3>
        } else {
            return <h3 className="text-center">Añadir Usuario</h3>
        }
    }


    render() {
        return (
            <div>
                <div className="container">
                    <div className="row">
                        <div className="card col-md-6 offset-md-3 offset-md-3">
                            {
                                this.getTitle()
                            }
                            <div className="card-body">
                                <form>
                                    <div className="form-group">
                                        <label>Nombre: </label>
                                        <input placeholder="Nombre" name="firstName" className="form-control" value={this.state.firstName} onChange={this.changeFirstNameHandler} />
                                    </div>
                                    <div className="form-group">
                                        <label> Apellidos: </label>
                                        <input placeholder="Apellidos" name="lastName" className="form-control" value={this.state.lastName} onChange={this.changeLastNameHandler} />
                                    </div>
                                    <div className="form-group">
                                        <label> Email: </label>
                                        <input placeholder="Email" name="email" className="form-control" value={this.state.email} onChange={this.changeEmailHandler} />
                                    </div>
                                    <div className="form-group">
                                        <label> Contraseña: </label>
                                        <input placeholder="Contraseña" name="password" className="form-control" value={this.state.password} onChange={this.changePasswordHandler} />
                                    </div>
                                    <button className="btn btn-success" onClick={this.saveOrUpdateUser}>Guardar</button>
                                    <button className="btn btn-danger" onClick={this.cancel.bind(this)} style={{ marginLeft: "10px" }}>Cancelar</button>
                                </form>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        )
    }
}

export default CreateUserComponent;

If it doesn't work please share the snippets that show how you've come to /add-user/add like onClick of Header Link or Add button in ListUserComponent.

CodePudding user response:

I guess this is because of cache

The browser caches the entire page for the browser performance

You might have noticed that when to visit a new page the action takes much time and if you press back (chrome back button) the page views fast

That is why there is no state change in the app and your component will not re-render You should block chrome back button or use useRouter for previous page

CodePudding user response:

If you go back, it's normal that it use cache instead of reload.

  • Related