简体   繁体   中英

React SPA routing on wordpress back-end

I have a small react SPA. It is hosted on WP back-end.

At the moment, only the landing page is working. This landing page had 2 sub-pages (one for health, and one for disease. Navigating through the links, I can see the urls look as I intend, but not in behaviour.

The wordpress server is throwing 404 errors when I try go to MAIN_URL/health or MAIN_URL/disease. I would have thought the urls matched the destination, but clearly need some help to see what is incorrect.

In App.js

import { BrowserRouter, Switch, Route } from 'react-router-dom';
import './App.css';
import Landing from './pages/Landing';
import HealthyHeartsHome from './pages/HealthyHearts/HealthyHeartsHome.js';
import HeartDiseaseHome from './pages/HeartDisease/HeartDiseaseHome.js';

class App extends Component {
  render() {
    return (
      <div className="App">
        <div className="AppContent">
          <BrowserRouter basename="/client/boehringer/BI33103/">
            <Switch>
              <Route exact path="/" component={Landing}></Route>
              <Route path="/healthy-hearts" component={HealthyHeartsHome}></Route>
              <Route path="/heart-disease" component={HeartDiseaseHome}></Route>
            </Switch>
        </BrowserRouter>
        </div>
      </div>
    );
  }
}

export default App;

Their troubles are surfacing

import Header from '../components/common/Header.js';
import LandingBanner from '../components/landing/LandingBanner.js';
import LandingNavgrid from '../components/landing/LandingNavgrid.js';
import LandingAd from '../components/landing/LandingAd';
import Footer from '../components/common/Footer.js';

class Landing extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
        };
    }

    componentDidMount(){
        document.title = "Heart Health";
    }

    render() {
        return (
            <div className="Landing">
                <Header/>
                <LandingBanner/>
                <LandingNavgrid/>
                <LandingAd/>
                <Footer/>
            </div>
        )
    }
}

export default Landing;

In LandingNavgrid.js

import React from 'react';
import { Link } from 'react-router-dom';
import './LandingNavgrid.css';
import grid1 from '../../assets/landing/grid1.png';
import grid2 from '../../assets/landing/grid2.png';
import grid3 from '../../assets/landing/grid3.png';
import grid4 from '../../assets/landing/grid4.png';

class LandingNavgrid extends React.Component {

    render() {
        return (
            <div className="LandingNavgridShell">
                <div className="LandingNavgridContent">
                    <div className="NavgridElement">
                        <Link to="./healthy-hearts" className="NavgridElementLink NavgridElement1">
                            <p className="NavgridText">Healthy Hearts</p>
                            <img src={grid1} className="NavgridImage" alt="Dog"/>
                        </Link>
                    </div>
                    <div className="NavgridElement">
                        <Link to="./heart-disease" className="NavgridElementLink NavgridElement2">
                            <p className="NavgridText">Heart Disease</p>
                            <img src={grid2} className="NavgridImage" alt="Dog"/>
                        </Link>
                    </div>
                    <div className="NavgridElement">
                        <Link to="./" className="NavgridElementLink NavgridElement3">
                            <p className="NavgridText">Benefits of early diagnosis</p>
                            <img src={grid3} className="NavgridImage" alt="Dog"/>
                        </Link>
                    </div>
                    <div className="NavgridElement">
                        <Link to="./">
                            <p className="NavgridText">Care and treatment</p>
                            <img src={grid4} className="NavgridImage" alt="Dog"/>
                        </Link>
                    </div>
                </div>
            </div>
        )
    }
}

export default LandingNavgrid;

Does "wordpress backend" mean that the SPA is being served from WordPress-on-Apache from within a WordPress post/page? Or does it mean you are running a "headless" CMS with the SPA being served from a separate server (using eg node/Express or cloud-SPA hosting etc).

If you are using the traditional WordPress/Apache server approach, the problem is that while you are using React-Router to set up in-memory javascript routes, the Apache webserver doesn't know anything about those routes.

So if you type in the url MAIN_URL/health , Apache looks for a file or directory on disk called "health". (Apache can also be configured to use aliases, rewrites, and all kinds of other redirection etc, but I'm assuming you didn't configure any of that). When it doesn't find that file, it returns 404. Your actual SPA files were never served by Apache, so React-Router had no chance of loading.

Now, if you start with your landing page, I think that clicking the React-Router links should take you to the correct in-memory SPA pages without making any requests to Apache. But if you ever refresh your browser or try to link directly to one of your routes (other than the landing page), then the request does go to Apache, and you will get the 404 error.

You can configure Apache, using rewrites or aliases etc. to always serve your main SPA page for any url under MAIN_URL , and that is probably what you should look into.

The httpd.conf rule might look something like this:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteRule ^index\.html$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.html [L]
 </IfModule>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM