My React application is hosted at www.mywebsite.com/myreact
When I defined my routes, I've done something like this:
<Router history={history}>
<Route path="/" component={App} />
<Route path="login" component={Login} />
</Route>
</Router>
Although, it keeps complaining that /myreact is not defined in the route.
When I define it, that way:
<Route path="/myreact" component={App} />
and I try to access the URL www.mywebsite.com/myreact/login, the browser throw a 404 error.
But I can access www.mywebsite.com/myreact properly though.
What should I do?
Thanks.
You should be able to create a custom history object with a different basename for your apps 'root' url. with the useRouterHistory enhancement when creating the history object
https://github.com/reactjs/react-router/blob/master/docs/API.md#userouterhistorycreatehistory
some relavent comments in this github issue thread
import { createHistory } from 'history';
import { useRouterHistory } from 'react-router';
const browserHistory = useRouterHistory(createHistory)({
basename: '/myreact'
});
your routes files should now work using browserHistory
<Router history={browserHistory}>
<Route path="/" component={App} />
<Route path="login" component={Login} />
</Route>
</Router>
Related
I have made use of react js memory router as below in my App.js -
import logo from './logo.svg';
import './App.css';
import './Components/Login'
import Login from './Components/Login';
import {useSelector} from 'react-redux';
import { useEffect } from 'react';
import Welcome from './Components/Welcome';
import{MemoryRouter as Router, Route, Switch} from 'react-router-dom'
function App() {
const state = useSelector(state => state.allReducers)
console.log(state.user.isValid);
return (
<Router>
<Switch>
<Route exact="/" component={Login}></Route>
<Route exact="/" component={Welcome}></Route>
</Switch>
<div className="App">
{state.user.isValid==false ||state.user.isValid== undefined ? <Login></Login> : <Welcome name={state.user.userName}></Welcome>}
</div>
</Router>
);
}
export default App;
But this is displaying my Login component twice on the screen.
How can I avoid this?
Your route configs should be:
<Switch>
<Route path="/login" component={Login} />
<Route path="/" component={Welcome} exact={true} />
</Switch>
exact should be a boolean value. And it'll tell the router only render the route match exactly with the URL. It means, the router only renders the Welcome component when the user stays at /.
But after you changed to my suggestion, you still see 2 login forms if you navigate to /login. Because the div.app will be rendered for every route :D
You're using the same route for both components: <Route exact="/"... so React will show you both. Use different routes for each component. And your syntax is a bit wrong. Like this:
<Switch>
<Route exact path="/"><Welcome /></Route>
<Route exact path="/login"><Login /></Route>
</Switch>
I was using the following code from an online course for React routing:
import { Router, Route, browserHistory } from 'react-router';
ReactDOM.render(
<Router history={browserHistory}>
<Route path="/" component={App></Route>
<Route path="/One" component={One}></Route>
<Route path="/Two" component={Two}></Route>
</Router>, document.getElementById('root'));
It gave me a following error 'react-router' does not contain an export named 'browserHistory'.
I did some research and found that I was using React Router v4, and the above code was for v3, so i found that I should be using <BrowserRouter> instead of <Router> so I changed my code to:
import { BrowserRouter, Route, Switch } from 'react-router-dom';
ReactDOM.render(
<BrowserRouter history={History}>
<div>
<Route path="/" component={App}></Route>
<Route path="/One" component={One}></Route>
<Route path="/Two" component={Two}></Route>
<Route path="*" component={NoMatch}></Route>
</div></BrowserRouter>, document.getElementById('root'));
History I have in a separate file:
import { createBrowserHistory } from 'history'
export default createBrowserHistory();
Now the page loads without an error but if I use Developer tools, I can see a warning:
Warning: <BrowserRouter> ignores the history prop. To use a custom history, use `import { Router }` instead of `import { BrowserRouter as Router }`."
Another issue is that <Route path="*" component="NoMatch}></Route> only supposed to load NoMatch component when no path specified in the router but it loads on every page, regardless.
Can anyone help figure out how can I fix the issues?
I am assuming you are using react-router v4
Firstly, Instead of <BrowserRouter> make use of <Router>
import { Router } from 'react-router-dom';
You can get access to the history object's properties by using <withRouter> as mentioned Here
Export the component using <withRouter> , something like :
import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
class SomeComponent extends Component {
render() {}
}
export default withRouter(SomeComponent);
Secondly , you can make use of <Switch> as it renders the first child <Route> or <Redirect> that matches the location
And you can wrap a <Switch> in a <div> like this:
<Router>
<div>
<Switch>
<Route path="/" component={App}></Route>
<Route path="/One" component={One}></Route>
<Route path="/Two" component={Two}></Route>
<Route component={NoMatch}></Route>
</Switch>
</div>
</Router>
NOTE : Last Route doesn't have path="*"
You can read more about <Switch> on a ReactTraining Github
If you want to read more about React Router V4 or <withRouter> , You can read on this Medium Article
You can only use history with <Router> hence the error message.
See the API on the sidebar in react-router docs.
Browser Router
<BrowserRouter>
basename: string
getUserConfirmation: func
forceRefresh: bool
keyLength: number
children: node
Router
<Router>
history: object
children: node
https://reacttraining.com/react-router/web/api/Router/history-object
As for the no match, you need a switch and to put the last component without a path. Right now you are grabbing every route with path="*"
Again, see docs https://reacttraining.com/react-router/web/example/no-match
<Switch>
<Route path="/" exact component={Home}/>
<Redirect from="/old-match" to="/will-match"/>
<Route path="/will-match" component={WillMatch}/>
<Route component={NoMatch}/>
</Switch>
I am using the tutorial found here:
https://github.com/reactjs/react-router-tutorial/blob/master/lessons/14-whats-next/modules/routes.js
However when copying:
module.exports = (
<Route path="/" component={App}>
<IndexRoute component={Home}/>
<Route path="/repos" component={Repos}>
<Route path="/repos/:userName/:repoName" component={Repo}/>
</Route>
<Route path="/about" component={About}/>
</Route>
)
Webstorm is highlighting the brackets and using:
import React from 'react'
import { Router, browserHistory } from 'react-router'
import routes from './routes'
But routes throws the error
Default export is not declared in imported module
The page just loads blank with no react code. Why can I not export the module as shown in the tutorial code?
The rest of my code is ES6
This issue was posted here
Changing in AppActions
module.exports = alt.createActions(AppActions);
To:
export default alt.createActions(AppActions);
Makes WebStorm happier and doesn't seem to break anything.
rselvaganesh is technically correct, however in this case it should be:
export default (
<Route path="/" component={App}>
<IndexRoute component={Home}/>
<Route path="/repos" component={Repos}>
<Route path="/repos/:userName/:repoName" component={Repo}/>
</Route>
<Route path="/about" component={About}/>
</Route>
)
with no name - which is what was confusing me
Given this React router configuration:
<Router history={browserHistory}>
<Route path="/farm/:type?period=:period" component={Farm} />
<Route path="/pen/:penId" component={Pen} />
<Route path="/pen/:penId/cow/:cowId" component={Cow} />
<Route path="*" component={Farm} />
</Router>
Why is http://localhost:8080/farm/average?period=day only matching the catch-all route and not the first one?
Query string parameters don't need to be included in the <Route> definition.
Changing the route definition to <Route path="/farm/:type" component={Farm} />
solved the problem.
Query string parameters are still available under props.location.query
I am trying to implement the following nested urls with react-router. My problem is that the Feed component sends both GET and POST requests to the wrong url when nested within the Router component, like this:
ReactDOM.render((
<Router history = { browserHistory }>
<Route component={ NavBar }>
<Route path='/' component={ Feed } url='/api/threads' pollInterval={ 2000 } />
<Route path='signup' component={ Signup } />
</Route>
</Router>
), document.getElementById('root'));
sends requests to http://localhost:3000/?_=1463499798727 which returns the content of index.html, which causes an error since the ajax request is expecting json data, not html, and is wrong anyway.
while
ReactDOM.render((
<Router history = { browserHistory }>
<Route component={ NavBar }>
<Route path='signup' component={ Signup } />
</Route>
</Router>
), document.getElementById('root'));
ReactDOM.render(<Feed url='/api/threads' pollInterval={ 2000 }/>, document.getElementById('feed'))
sends requests to the expected url http:localhost:3001/api/threads and returns data, and everything works normally.
As a side note, I have port 3000 set for the webpack-hot-load frontend and port 3001 set for the Express backend.
On the Express side, I have the following route set:
router.get('/api/threads', function (req, res, next) {
Thread.find(function (err, threads) {
if (err) { return next(err); }
res.json(threads)
})
})
Visiting localhost:3001/api/threads returns the expected data.
localhost:3001 returns Cannot GET '/' which is expected.
First, if a URL is intended to be used as an API endpoint and not directly in the browser then it probably does not belong in your react-router at all. Only put paths in the router that you expect to render a view in the browser. So if you want localhost:3001/api/threads to return JSON via an API call, take it out of your router.
Also, you use should organize your routes using IndexRoute. Try this:
<Router history={browserHistory}>
<Route path="/" component={CoreLayout}>
<IndexRoute component={Feed} />
<Route path="signup" component={Signup} />
<Route path="*" component={NotFoundView} />
</Route>
</Router>
Where CoreLayout simple renders it's children. I'm not sure exactly what you are trying to display for the root URL (localhost:3001) but you would use a component like above.
To use your API endpoint you can just call it in the component directly via it's full path (localhost:3001/api/threads).