React Router - Take over at root URL - react-router

So I've got React Router set up and I'm trying to run it from WordPress.
The app routes correctly as long as you start from the root "/". However if you manually navigate to any subpage via the address bar, React Router seems to only take over from there.
For example.
Hitting / will render the homepage. If you click the link 'style-guide' it will correctly route you to /style-guide and render the page.
However, if you manually navigate to /style-guide in your address bar, react will render the homepage there, and if you now click the style-guide link it will bring you to /style-guide/style-guide
What I need to do is tell react-router to always start from the root URL.
My Routes Look Like this
import {
BrowserRouter as Router,
Route,
Redirect,
Switch,
} from 'react-router-dom'
import PageContainer from 'containers/pageContainer'
class RoutesList extends React.Component {
render() {
return (
<Router>
<div>
<Switch>
<Route path="/" component={PageContainer} />
<Route path="style-guide" component={PageContainer} />
<Route
render={() => {
return <Redirect to="/" />
}}
/>
</Switch>
</div>
</Router>
)
}
}
export default RoutesList

Make your routes exact paths
<Route exact path="/" component={PageContainer} />
<Route exact path="/style-guide" component={PageContainer} />

Related

Changing landing page for react website , localhost

I deployed one website on localhost, with npm build / react, and I would like to select another landing page.
However I'm a newbie working with React and I don't know where to find the routes for the pages. I have the following codes in the public/Index.html, public/manifest.json, and package.json from root folder.
I tried modifying the homepage in package.json to another folder/.ts/.tsx files but without any success.
Any idea in how to find the routes to other pages and how to set the landing page to them for localhost server ?
you don't touch the public folder for routes, and assuming you want to link to another page like you want to go from / to /about then you need to do this:
this will be your home page - app.tsx
import { BrowserRouter, Routes, Route} from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About/>} />
</Routes>
</BrowserRouter>
);
}
this will be your about file, about.tsx
import { Link } from 'react-router-dom';
function About() {
return (
<div>
<nav>
<Link to="/">Home Page</Link>
</nav>
</div>
);
}
To understand more about routes please check the documentation below
React router V6

React Router + GH Pages, refresh breaking app

This isn't happening on my local server,
but when I push my create-react-app to gh-pages and try to reload anything besides the home page, or navigate directly to a routed page, the page breaks and the URL repeatedly grows looking like this...
https://hellocentral.live/about/?p=/&q=p=/~and~q=p=/~and~q=p=/~and~q=p=/~and~q=p=/~and~q=p=/~and~q=p=/~and~q=p=/~and~q=p=/~and~q=p=/~and~q=p=/~and~q=p=/~and~q=p=/~and~q=p=/~and~q=p=/~and~q=p=/~and~q=p=/~and~q=p=/~and~q=p=/~and~q=p=/....
Here is my file with my routes...
import React from "react";
import "./SiteContainer.scss";
import HeaderContainer from "../HeaderContainer/HeaderContainer";
import { Route, Switch } from "react-router-dom";
import About from "../About/About";
import Home from "../Home/Home";
import Music from "../Music/Music";
import Footer from "../Footer/Footer";
import Merch from "../Merch/Merch";
import Pics from "../Pics/Pics";
import Contact from "../Contact/Contact";
export const SiteContainer = () => {
return (
<div className="site-container">
<HeaderContainer />
<Switch>
<Route path="/about" component={About} />
<Route path="/merch" component={Merch} />
<Route path="/music" component={Music} />
<Route path="/pics" component={Pics} />
<Route path="/contact" component={Contact} />
<Route path="/" component={Home} />
</Switch>
<Footer />
</div>
);
};
export default SiteContainer;
here is my repo
https://github.com/monstaro/hc3/tree/master/src
The site is https://www.hellocentral.live
Any help would be appreciated!
You need to wrap the Switch component in a Router component. To do this, you need to import it from the react-router-dom package:
import { HashRouter as Router } from 'react-router-dom'
...
<Router basename={process.env.PUBLIC_URL}>
<Switch>
...
</Switch>
</Router>
I gave HashRouter as example because GH Pages does not support the other router, BrowserRouter. Probably, MemoryRouter or StaticRouter do work, but I am not sure.
Since your domain is https://www.hellocentral.live, you need to set segmentCount to 0 here.
Guess you're using an older version of rafgraph/spa-github-pages cited in a blog or something. I would recommend updating index.html with the latest version of the script and 404.html with this script.
From the docs,
Note that if you are setting up a Project Pages site and not using a custom domain (i.e. your site's address is username.github.io/repo-name), then you need to set pathSegmentsToKeep to 1 in the 404.html file in order to keep /repo-name in the path after the redirect.

React Router props `location` / `match` not updating with `ConnectedRouter`

I've got my app setup as in the docs:
Step 1
...
import { createBrowserHistory } from 'history'
import { applyMiddleware, compose, createStore } from 'redux'
import { connectRouter, routerMiddleware } from 'connected-react-router'
...
const history = createBrowserHistory()
const store = createStore(
connectRouter(history)(rootReducer), // new root reducer with router state
initialState,
compose(
applyMiddleware(
routerMiddleware(history), // for dispatching history actions
// ... other middlewares ...
),
),
)
Step 2
...
import { Provider } from 'react-redux'
import { Route, Switch } from 'react-router' // react-router v4
import { ConnectedRouter } from 'connected-react-router'
...
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}> { /* place ConnectedRouter under Provider */ }
<div> { /* your usual react-router v4 routing */ }
<Switch>
<Route exact path="/" render={() => (<div>Match</div>)} />
<Route render={() => (<div>Miss</div>)} />
</Switch>
</div>
</ConnectedRouter>
</Provider>,
document.getElementById('react-root')
)
I click on a Link or even dispatch(push('/new-url/withparam'))
However the props for match location are remaining the previous values or whatever the first page was.
What is happening?
This one has bitten me many times.
Your Switch and Route etc. MUST NOT BE INSIDE A CONNECTED COMPONENT!
If the component is connected, the props for match, location, etc. don't seem to get updated and propagate down to your routes.
This means don't connect your top level App or Root, or any other nested containers between the ConnectedRouter and Route
--
Update:
You may just need to wrap your component with
<Route render={ (routerProps) => <YourConnectedComponent { ...routerProps } />
I decided to add example to here as I feel it is valuable input - even tho, it's already answered.
I had similar problem, when I pushed url into router history, it changed URL but it didn't navigate properly on the component I wanted. I googled and searched for answer for hours, until I found this thread which finally helped me to find out what I made wrong. So all credits to #ilovett.
So here is an example, if someone will need it for better understanding:
I had code similar to this:
export const routes =
<Layout>
<Switch>
<Route exact path='/' component={ Component1 } />
<Route path='/parameter1/:parameterValue' component={ Component2 } />
</Switch>
</Layout>;
<Provider store={ store }>
<ConnectedRouter history={ history } children={ routes } />
</Provider>
It was working fine when I came to a project, but then I decided to refactor Layout component and I connected it to the store which caused that Component2 stopped receiving correct values in the ownProps.match.params.parameter1 and because of that it rendered component completely wrong.
So only thing what you need to do is move Layout outside of ConnectedRouter. Nothing between ConnectedRouter and Route can be connected to the store.
Working example is this then:
export const routes =
<Switch>
<Route exact path='/' component={ Component1 } />
<Route path='/parameter1/:parameterValue' component={ Component2 } />
</Switch>;
<Provider store={ store }>
<Layout>
<ConnectedRouter history={ history } children={ routes } />
</Layout>
</Provider>

React router v4 routes setup

During the migration from v2 to v4, my routes are now set up like so:
ReactDOM.render(
<Provider store={store}>
<Router>
<Route path='/admin' component={App} />
</Router>
</Provider>
, document.getElementById('root'))
with the app component being
class App extends Component {
render() {
return (
<AppContainer>
<Switch>
<Route path="/admin/dashboard" component={Dashboard} />
<Route path="/admin/signin" component={SignIn} />
<Route path="/admin/settings" component={Settings} />
</Switch>
</AppContainer>
);
}
}
In the app container, it calls an action which checks the login and then router.history.push('/admin/dashboard') if the login is valid. The rest of the AppContainer component is
render() {
return (
<div>
{this.props.children}
<Detached />
</div>
)
}
Going to /admin sends you to /admin/dashboard correctly.
Going to /admin/dashboard 404's, seemingly not even matching the first route path "/admin".
Am I doing anything blatantly wrong? Shouldn't going to /admin/xxxxx be matched by the first route?
It would be helpful to know where your 404 route is and whether there is any logic governing the push to '/admin/dashboard.
'/admin/xxxxx' should definitely result in a match for '/admin' as long as there is no 'strict' or 'exact' prop.
Potential error: If the logic in AppContainer checks login status and performs push to '/admin/dashboard' regardless of current pathname, then your app may be falling into the below recursive cycle:
User navigates to '/admin'
Route checks pathname '/admin' against path prop '/admin' and finds a match
Route renders 'App' component
AppContainer verifies that user is logged in
AppContainer pushes user to '/admin/dashboard'
Application rerenders with pathname '/admin/dashboard'
Route checks pathname '/admin/dashboard' against path prop '/admin' and finds a match
Route renders App component
AppContainer verifies that user is logged in
AppContainer pushes user to '/admin/dashboard'
Application rerenders with pathname '/admin/dashboard'
...
The simplest fix to implement would be to only push to '/admin/dashboard' if pathname is '/admin'.
A fix with arguably less cognitive overhead would be to remove the manual history.push to '/admin/dashboard' and change App to the following:
class App extends Component {
render() {
return (
<AppContainer>
<Switch>
<Route exact path="/admin" render={() => <Redirect to='/admin/dashboard' />} />
<Route path="/admin/dashboard" component={Dashboard} />
<Route path="/admin/signin" component={SignIn} />
<Route path="/admin/settings" component={Settings} />
</Switch>
</AppContainer>
);
}
}

Routing not working in reactjs application

I have created a reactjs app having three pages (components), App, Login and Register, where I need to navigate from page to page by entering the url in the browser but the navigation is not working for me. Entering any url just shows me the 'App' page.
following is the code that I have written in main.js file of the app and the url that I am using to navigate looks something like this http://localhost:8080/#/login or http://localhost:8080/#/reg
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route, NavLink, Redirect, Switch, hashHistory} from 'react-router-dom'
import App from './../jsx/App.jsx';
import Login from './../jsx/Login.jsx';
import Register from './../jsx/Register.jsx';
ReactDOM.render((
<Router history={hashHistory}>
<div>
<Route path="/" component={App}/>
<Route path="/login" component={Login}/>
<Route path="/reg" component={Register}/>
</div>
</Router>
), document.getElementById('app'))
You need to configure the route to match the root path exactly. Try this...
<Route exact path="/" component={App}/>
Remove / from your path in Route path in
<Route path="/login" component={Login}/>
<Route path="/reg" component={Register}/>
try this it's working for me
entry class
import React from 'react';
import ReactDOM from 'react-dom';
import Layout from './Component/Layout.jsx';
import { Router, Route, IndexRoute, hashHistory } from "react-router";
import Archives from './Component/Archives.jsx';
import Settings from './Component/Settings.jsx';
import Featured from './Component/Featured.jsx';
ReactDOM.render(
<Router history={hashHistory}>
<Route path="/" component={Layout}>
//<IndexRoute component={Featured}></IndexRoute>
<Route path="archives" name="archives" component={Archives}></Route>
<Route path="settings" component={Settings}></Route>
<Route path="featured" component={Featured}></Route>
</Route>
</Router>,
document.getElementById('app'));
Layout class
{
render{
return(
<div>
{this.props.children}
<ul>
<li><Link to="archives">archives</Link></li>
<li><Link to="settings">settings</Link></li>
<li><Link to="featured">featured</Link></li>
</ul>
</div>
);
}
}
If you are using react router 4, then that looks fine. However, you can try using a as shown below:
<BrowserRouter>
<Switch>
<Route path="/" component={Home} />
</Switch>
</BrowserRouter>
This is in latest versions of react. The Home component is as below:
render() {
return (
<div>
<p>Header Section</p>
<Header/>
<p>Home component</p>
<Link to="/search">search</Link>
<Route path="/search" component={Search}/>
</div>
);
}
So most probably what you need to do is to just add a switch. Other solutions may be possible too. Hope this helps :)
Use BrowserRouter and Switch from 'react-router-dom'
if you use BrowserRouter no need to pass history as props as it handles itself.
Try this.
<Router>
<Switch>
<Route exact path="/" component={App}/>
<Route exact path="/login" component={Login}/>
<Route exact path="/reg" component={Register}/>
</Switch>
</Router>