I have this simple code that doesn't work. I took it from the react-router project page and modified slightly for it to look a bit better.
Setup
I have several very simple react components:
var IndexPage = React.createClass({
render(){
return (<h1>Index Page</h1>);
}
});
var AboutPage = React.createClass({
render(){
return (<h1>About page</h1>);
}
});
var NotFoundPage = React.createClass({
render(){
return (<h1>Not found page</h1>);
}
});
Also I have made a setup of react router:
var ReactRouter = require('react-router');
var Router = ReactRouter.Router;
var Route = ReactRouter.Route;
var BrowserHistory = ReactRouter.browserHistory;
var Render = ReactDOM.render;
And that's how I use react router 2.0.
Render((
<Router history={BrowserHistory}>
<Route path="/" component={IndexPage}>
<Route path="about" component={AboutPage}/>
<Route path="*" component={NotFoundPage}/>
</Route>
</Router>
), document.body)
I use BrowserHistory (not HashHistory) to avoid hash in urls.
My server is raised under IIS 10 (Windows 10) on 8080 port.
Problem
http://localhost:8080/
goes to IndexPage component. This is correct.
http://localhost:8080/about
goes to IIS 404 error page. Routing doesn't work in this case
http://localhost:8080/ttt
goes to IIS 404 error page again.
So the router doesn't see this nested paths that go after /. And it doesn't even care about whether they are correct or not.
What can cause such a strange behavior?
Thanks in advance!
Update
I've found out that the next string solves the problem with a client routing:
{this.props.children}
This is the fixed code:
var IndexPage = React.createClass({
render(){
console.log('index page render');
return (<div>
<h1>Index Page</h1>
<Link to={ '/about' }>about</Link>
{this.props.children}
</div>);
}
});
Is your server configured to map all application-paths to your index.html? You should never get a IIS 404 if your server would map all path to your index file, as it always would deliver this one.
React-router is a client-side routing solution(also works in server side, but it seems you are using .Net as the server side handler).
You can try this(Link from React-Router):
<Link to={ pathname: 'about' }>
about
</Link>
Put it in the index page's component, and click the link, the react-router will work.
Update:
{this.props.children} ref to the inner component(AboutPage, NotFoundPage).
If you change code to that:
<Route path="/" component={IndexPage} />
<Route path="/about" component={AboutPage}/>
<Route path="*" component={NotFoundPage}/>
It will works.(remove the {this.props.children} in IndexPage if there is no nesting routes).
I was able to solve my issue linking directly to URLs by adding --history-api-fallback to my webpack-dev-server command.
Setting this flag prompts webpack-dev-server to serve the index page instead of 404. The index page will then route correctly on the client side.
Related
I'm working on a simple example using React Router.
I created it using create-react-app
On a local server, each link goes well
ex) localhost:3000/login, localhost:3000/ product, etc.
After deploying to my domain, I get a 404 error when I enter my link.
ex) myDomain.com/login, myDomain.com/product
It looks good on the local server, so I think there's no problem with the source code.
Then, I received an answer to redirect to the index.html page when the 404, 403 ... etc page appears
Are localhost:3000 and localhost:3000/index.html the same?
On the main page (localhost: 3000 or myDomain.com),
is well rendered.
In index.html (localhost: 3000 / index.html or myDomain.com/index.html)
it only renders up to h1 tag above {Home}. Is something wrong from here?
Please help me T.T
App.js
class App extends Component{
render(){
return (
<div className="App">
<Header/>
<h1>asd</h1>
<h1>asd</h1>
<Route exact path = "/" component = {Home}/>
<Route path = "/about" component = {About}/>
<Route path = "/event" component = {Event}/>
<Route path = "/qna" component = {QnA}/>
<Route path = "/login" component = {Login}/>
<Route path = "/join" component = {Join}/>
<Route path = "/product" component = {Product}/>
</div>
);
}
}
export default App;
Root.js
const Root = () => {
return (
<BrowserRouter>
<App/>
</BrowserRouter>
);
};
export default Root;
You can wrap your route components in a switch component and render a default component if none match like below.
<Switch>
<Route exact path = "/" component = {Home}/>
<Route path = "/about" component = {About}/>
<Route path = "/event" component = {Event}/>
<Route path = "/qna" component = {QnA}/>
<Route path = "/login" component = {Login}/>
<Route path = "/join" component = {Join}/>
<Route path = "/product" component = {Product}/>
<Route component={NoMatch} />
</Switch>
Obviously you'd change the NoMatch component with whatever you'd want your default component to be.
You should add the basename to the BrowserRouter component in the root
ReactDOM.render(
<BrowserRouter basename='/My-App/'>
<React.StrictMode>
<App />
</React.StrictMode>
</BrowserRouter>
,
document.getElementById('root')
);
Also, you should make sure in 404 cases you are redirected to index.html because it's a SPA and everything is happening there, you do this by simply replacing this line with "build" script in package.json
"build": "react-scripts build && cp build/index.html build/404.html",
I don't think this is your react app issue, rather it's how your app is deployed.
I hope you have deployed your app using production build (using npm run build).
If so, this is most likely that your web server is not redirecting to the right entry.
You need to tell your web server(nginx or caddy whatever you are using) to point to /index.html when hitting 404. Here is a simple config for nginx.
https://www.barrydobson.com/post/react-router-nginx/
I've been trying to create a SPA on an electron project using React, React-Router and typescript (boostrapped from here).
I'm currently just trying to make it reroute to a different route via a <Link> but I'm getting an error in the console saying
Uncaught DOMException: Failed to execute 'pushState' on 'History': A history state object with URL 'http://settings/' cannot be created in a document with origin 'http://localhost:2003' and URL 'http://localhost:2003/'.
where localhost:2003 is the port associated with the project. I'm not sure how I can fix this as I believe this is a problem specific with electron? Not sure..
The code I'm running is exactly the same as https://codesandbox.io/s/weathered-river-9yrbv
(please to go /app first in the sandbox)
You mad mistake to load props in App function.
function App(props) {
console.log(props);
return (
<div className="App">
{/* {props} // Remove this line... */}
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<ProtectedRoute path="/app" component={MainComponent} />
</div>
);
}
You have to wrap App component via Route.
import { BrowserRouter as Router, Link, Route } from "react-router-dom";
...
...
render(
<Router>
<Route path="/" component={App}/>
</Router>,
rootElement
);
Now you can get the props in console.log.
Here is the updated working code for you.
https://codesandbox.io/s/elegant-elion-qr1qf
Hope this will work for you!
I am using react router with my application and everything works fine locally. Below is my code. The issue is when I host it online it is in a my-application subdirectory:
https://www.example.com/my-application
This is breaking the code and it is not functioning as it should.
can anyone advise how to fix this issue? If there is anything unclear please feel free to ask. I have tried countless approaches but cannot get it to work. One answer can be seen here.
the issue I am getting is that with the current code it navigates to https://www.example.com/test as opposed to https://www.example.com/my-application/test. I thought if I hardcoded in the url it would work but this also breaks the application.
The code below is slightly whittled down to remove superfluous code.
import React, { Component } from 'react';
import styled from 'styled-components'
import { Route, Switch } from 'react-router-dom'
const Home = ({ avatarUrl }) => {
return (
<div>
<Route exact path="/" component={Overview}/>
<Route path="/test" component={Test}/>
</div>
);
};
class App extends Component {
render() {
return (
<section>
<Nav avatarUrl={ this.props.avatarUrl }/>
<Switch>
<Route path="/example" component={Example}/>
<Route path="/" render={()=><Home
avatarUrl={ avatarUrl }
/>}/>
</Switch>
</section>
)
}
}
export default App
Apply config changes pacakage.json add homepage page as your folder name
To solve this I just did two things:
Added "hostname": "https://www.example.com/my-application" at the top of package.json.
Added basename="my-application" to the BrowserRouter e.g. <BrowserRouter basename="my-application">
Note: I created the project using create-react-app. I am using react version 18 and react-router version 6.
I am using an express server to serve a create-react-app build.
server.js
// Express only serves static assets in production
if (process.env.NODE_ENV === 'production') {
server.use(express.static('client/build')); // <--- this might be causing my problem, how to make work?
}
var api = require('./routes/api');
var email = require('./routes/email');
// Define API routes before the *
server.use('/api', api);
server.use('/email', email);
server.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
app.js
class App extends Component {
render() {
return (
<Router history={browserHistory}>
<Route component={Container}>
<Route path="/" component={Main} />
<Route path="/catalog" component={Catalog} />
<Route path="/product/:productId" component={ProductPage} />
<Route path="/faq" component={Faq} />
<Route path="/blog" component={Blog} />
<Route path="/inquiry" component={Inquiry} />
<Route path="/cart" component={Cart} />
</Route>
</Router>
);
}
}
export default App;
Edit:
Updated my server.js file to show relevant code. I think the issue lies in using express.static('client/build'), but I'm not quite sure what to change it to in order to fix my routing issues.
/Edit
This works perfectly fine in Dev and Heroku where clicking links in the app go from route to route. For example being at the root, I can click on a link to "https://thesite.com/catalog" and the app navigates there as with any other route.
However, if I were to copy the URL above and paste it into a new tab/browser, I get a 500 Internal Server Error. This would mean the user cannot bookmark any page other than the root. Or if another site linked to a specific route on my page it would show a 500 error. Refreshing in a page that isn't "/" returns a 500 error. Does anyone know how to fix this?
Figured it out. I needed to add a universal route getter for express.static('client/build').
if (process.env.NODE_ENV === 'production') {
server.use(express.static('client/build'));
server.use('*', express.static('client/build')); // Added this
}
I have an issue using nested routes with react-router.
Here is my code (two simple react components, routes file to access comp1/comp2) :
House.js
export default connect(st => st)(class House extends React.Component {
render() {
return (
<div>
{this.props.children}
</div>
);
}
})
Window.js
export default connect(st => st)(class Window extends React.Component {
render() {
return (
<div >
hey hey
</div>
);
}
})
routes.js
export const routes = (
<Router history={ history }>
<Route path="/house" component={House}>
<Route path="/house/window" component={Window} />
</Route>
</Router>
);
When I redirect to "/house/window" programmatically, I can access the route and the page shows "hey hey".
If I want to access the url directly :
localhost:8080/house/window
It shows a blank page and a console error :
Request URL:http://localhost:8080/house/window
Request Method:GET
Status Code:304 Not Modified
And then :
GET http:// localhost:8080 /house/js/bundle.js (404)
Also, http:// localhost:8080 /house/ (with trailing slash) shows the same error.
I really don't understand this weird redirection http:// localhost:8080 /house/js/bundle.js
I'm probably doing something wrong, but after crawling stackoverflow, I still can't see it.
I found the issue : my bundle.js script included in index.html was included with a relative path 'js/bundle.js' so I changed it for '/js/bundle.js'.
Sadly, it didn't make any problem until I wanted to nest some routes.
Nested routes cannot have parent path included in path attribute:
export const routes = (
<Router history={ history }>
<Route path="/house/" component={House}>
<Route path="window" component={Window} />
</Route>
</Router>
);