javascriptreactjsclassreact-routerhttp-status-code-404

Getting "Cannot GET /exams/0" upon page refresh in my react class-based app, using router


When I click on specific exam, the url changes and the specific exam renders, but then on page refresh, the information is lost and i get -> Cannot GET /exams/0 for example. How to make the page keep its content on page refresh?

export const dummyExams = [
  {
    title: "Software Testing Fundamentals",
    content:
      "This QA exam covers the basic principles and techniques of software testing, including test planning, test case design, and defect management.",
  },
];

export default class FrontPage extends Component {
  constructor(props) {
    super(props);
    this.state = {
      loading: false,
      isExamOpen: false,
      exams: [],
    };

    this.setIsExamOpen = this.setIsExamOpen.bind(this);
  }

  setIsExamOpen() {
    this.setState((prevState) => ({
      isExamOpen: !prevState.isExamOpen,
    }));
  }

  componentDidMount() {
    this.setState({ exams: dummyExams });
  }

  render() {

    return (
      <div className="Front-Page">
     
        <div className="Content-Holder">
          <main className="Main">
            <Routes>
              <Route
                path="/"
                element={this.state.exams.map((exam, i) => {
                  return (
                    <FrontPageExam
                      title={exam.title}
                      text={exam.content}
                      className={
                        this.state.exams.length - i <= 2 ? "Last-Exam" : "Exam"
                      }
                      key={i}
                      setIsExamOpen={this.setIsExamOpen}
                      id={i}
                    />
                  );
                })}
              ></Route>
              <Route path="exams/:id" element={<DetailedExam />}></Route>
              <Route path="/*" element={<Navigate to="/" />}></Route>
            </Routes>
          </main>
        </div>
      </div>
    );
  }
}

This is the component for specific exam:

class FrontPageExam extends Component {
  constructor(props) {
    super(props);
    // this.state = {
    //   showDetailedExam: false,
    // };
    this.onClickExam = this.onClickExam.bind(this);
  }

  onClickExam() {
    this.props.setIsExamOpen();
  }

  render() {
    return (
      <Link to={`/exams/${this.props.id}`}>
        <div
          className={this.props.className}
          // className="-mt4 -mb3 -fw4"
          onClick={this.onClickExam}
        >
          <div className="Exam-content">
            <div className="Exam-title">
              <strong>{this.props.title}</strong>
            </div>

            <span>{this.props.text}</span>
          </div>
        </div>
      </Link>
    );
  }
}

export default FrontPageExam;

When I click on one exam, this is the component:

export default class DetailedExam extends Component {
  constructor(props) {
    super(props);

    this.state = {
      hasStarted: false,
    };

    this.startExam = this.startExam.bind(this);
  }

  startExam() {
    this.setState({
      hasStarted: !this.state.hasStarted,
    });
  }

  componentDidMount() {

  }

  render() {
    return (
      <div>
        {/* {this.state.hasStarted ? (
          <App 
          // examType={}
          />
        ) : ( */}
          <div>
            <h1>Hi</h1>
            <span>Yalla</span>
            <div>
              <span>
                ...
              </span>
            </div>
            <button onClick={this.startExam}>Start</button>
          </div>
        {/* )} */}
      </div>
    );
  }
}

Tried to do workaround, searched that I need backend file, but this is my first time when I do it with react class-based, so I am not sure this is the case


Solution

  • I have searched in stackoverflow posts and found an optimal solution for early stage of development of application, when there is no server configured to handle requests to certain URL in the app:

    import { HashRouter } from "react-router-dom";
    import FrontPageRoutes from "./components/UI/FrontPage_Routes";
    
    ReactDOM.render(
      <HashRouter>
        <Provider store={store}>
          <FrontPageRoutes />
        </Provider>
      </HashRouter>,
      document.querySelector("#root")
    );
    

    This is not the typical BrowserRouter, that you would have used in a normal situation, where you have back-end server to handle the url requests.

    Basically this approach ( with ) is not optimal for SEO, but is good workaround when you do not have server.

    Here is link to the post, that helped me: React-router URLs don't work when refreshing or writing manually