React Router 404 Page catch-all only works on index in deployed web build? - react-native

I've been struggling for the past day to get the react router working correctly for my React Native Web application. Namely, despite following quite a few guides on setting up a catch-all 404 page, the solutions only work from expo start on a local host test. In there, I can type any arbitrary address and activate the 404 page. However, with a deployed web build, the 404 page won't work unless I type /index after the address (www.example.com/index for example). If I type anything else that in theory should bring me to the 404 (such as www.example.com/alkjshdakh or even www.example.com/404), I get the following error in my browser:
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>9C6M8QSYEVZGCEXQ</RequestId>
<HostId>av+kOjxxgyXcIRSdeA7qRzVGuoigeCeiEQyDE/iJoQMYvmTjar4PV2d+3/IPoJO2T+9/NFkbDUs=</HostId>
</Error>
I'd like to reiterate that this only happens in deployed builds, and the 404 catches everything locally. Is there something I'm doing wrong? Or perhaps something I'm missing? My code for the project's App.js is posted below for reference:
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Switch, Redirect } from 'react-router-dom';
console.log("Importing....")
//WebPages
console.log("Importing pages");
import MainPage from "./assets/pages/index";
import NotFoundPage from './assets/pages/404';
//export default function App()
class App extends Component {
render() {
console.log("Loading... Pages");
return (
<Router>
<Switch>
<Route exact path = "/" component = {MainPage} />
<Route exact path = "/404" component = {NotFoundPage} />
<Redirect to = "/404" />
</Switch>
</Router>
);
}
}
export default App;

The problem likely isn't in your code, and if you're like me, it's an issue with AWS Amplify (assuming you're using it). To fix it, go to your AWS Amplify Console > Rewrites and Redirects. From there, create a new entry with the following parameters:
Source Address: </^((?!\.(css|gif|ico|jpg|js|png|txt|svg|woff|ttf)$).)*$/>
Target: /index.html
Type: 200 (Rewrite)
Source: #Vinit Khandelwal https://stackoverflow.com/a/63554987/17235602

Related

root component swizzle in docusaurus v2 not working

I am trying to wrap my website with a root component: https://docusaurus.io/docs/using-themes#wrapper-your-site-with-root. I made src/theme/Root.js with following code in it:
import React from 'react';
// Default implementation, that you can customize
function Root({children}) {
console.log('from root');
return <>{children}</>;
}
export default Root;
Now when I open up the browser console, I don't see any log. What could be the reason? I am using the classic preset with typescript support on
Fixed it by deleting .docusaurus folder and reinstalling the contents of node_modules

Page component of #shopify/polaris throws No features were provided

I'm following the Shopify tutorial to create their basic app using React.js and Node.
import { Layout, Page, TextStyle } from '#shopify/polaris';
const Index = () => (
<Page>
<Layout>
<TextStyle variation="positive">
Sample app using React and Next.js
</TextStyle>
</Layout>
</Page>
);
export default Index;
As soon as I introduce the Page component, it throws the following error:
Error: No Features were provided.
Any clues as to what could be wrong?
I faced the same issue, I fixed the issue by renaming app.js to _app.js or also could be that you have not placed _app.js in /pages directory or No wrapped the app with <AppProvider i18n={translations}> <AppProvider/>.
Please check out the
using-components section for instructions on wrapping application with <AppProvider><AppProvider/>

Express 404 page overlaps the react router

Hello
I have an express app running as a REST server, meaning all the /api/xx routes are process in express.
I also have a react app (served by express when accessing the /) as a client, which also has a router, the problem comes when i refresh a react route, the 404 page error of express shows up instead of the react page itself.
The react router
<Router history={browserHistory}>
<Route path="/" component={MainLayout} user={user}>
<IndexRoute component={DocumentsPage}></IndexRoute>
<Route path="about" component={AboutPage}></Route>
<Route path=":id/preview" component={PreviewPage}/>
<Route path="upload" component={UploadPage}></Route>
</Route>
</Router>
and when i access with a <Link to="upload" </Link> the page shows up, and when i refresh the page, i got the 404 express's page..
Any help would be lovely <3
You need to configure a fallback, so that every request that doesn't exist in your Express routing is redirected to your React app at /. Here's a basic example of how to do that with Express:
import fallback from 'express-history-api-fallback';
import express from 'express';
import http from 'http';
// Set up express
const app = express();
const server = http.createServer(app);
const root = `${__dirname}`;
// History Fallback for express
app.use(express.static(root));
app.use(fallback('index.html', { root }));
// Listen
server.listen(8080, '0.0.0.0');
Then you can also handle your 404 page with React Router.

react router server side rendering: How to get route params on server side?

OK, I'm still trying to build react.js app with server side rendering. I having big time dealing with react-router with parameters. I cannot extract routes params from route on server side to make proper query on DB.
Here is my react-router route:
import {Router,Route} from "react-router";
import React from "react";
import App from "../components/app";
import {HomeContainer} from "../components/home";
import {TagContainer} from "../components/tag";
export function createRouter(hist) {
const routes = <Route component={App}>
<Route path="/" component={HomeContainer}/>
<Route path="/tag/:unique_name" name="tag" component={TagContainer}/>
</Route>;
return (
<Router history={hist}>{routes}</Router>
);
}
the route run fine until I add parameter ":unique_name" to the route
<Route path="/tag/:unique_name" name="tag" component={TagContainer}/>
on the server side, I cannot extract unique_name from the route to make query on DB:
Here is the route on server(Using Node.js & Express.js):
const router = express.Router();
router.get("/tag/:unique_name", ServerRenderController.tagRender);
server.use(express.static(path.join(__dirname, '..', '/build')));
server.use(router);
and here is my "ServerRenderController.tagRender":
function tagRender(req, res) {
console.log(req.params.unique_name);
/*
output :
mytag_unique_name -> this is the route params
style.css ->stylesheet - how the hell it become route params?
app.js -> client code - how the hell it become route params?
vendor.js -> vendor scripts - how the hell it become route params?
manifest.js -> manifest file -how the hell it become route params?
*/
match({browserHistory,routes, location:req.url}, (err, redirectLocation, renderProps)=> {
if (redirectLocation) {
//#TODO: response redirect location
console.log('redirect location');
}
if (err) {
//#TODO: response error
console.log(err.stack);
}
if (!renderProps) {
//#TODO: route to 404
console.log("no renderProps");
}
renderPage(renderProps); // return HTML to client with __PRELOADED_STATE__
}
Questions :
What did I do wrong in server code (routing, express static
middleware...).
How do I extract correct route params from route? (I only want to extract "mytag_unique_name" as the only params when I browse to http://localhost/tag/mytag_unique_name)
right now the route params including static files that should be
send as MIMETYPE css/js.
OK. Turn out I made mistake in references to style sheets and scripts file.
In the server render code must refer <link href="/style.css" rel="stylesheet"/>
with slash (/) at the begining of the rel attr.
Note here for anyone have same problem.

How to send GET/POST requests using express and react router?

I currently have express set up to serve a static html page where my react components mount to. I'm also using react router because I have nested routes. For example:
I have an App component (green outline). Within that component, I'm rendering a Header component (orange outline) and a Footer component (red outline) and passing in a Review component (blue outline) through this.props.children.
My server.js file (express):
const express = require('express');
const app = express();
app.use(express.static('dist'));
const PORT = process.env.PORT || 3000;
app.listen(PORT, function() {
console.log(`Listening on port ${PORT}...`);
});
My routes.js file (react-router):
import React from 'react';
import ReactRouter, {
Router,
Route,
browserHistory,
IndexRoute,
} from 'react-router';
import App from '../components/App';
import Home from '../components/Home';
import Review from '../components/Review';
import Game from '../components/Game';
const routes = (
<Router history={browserHistory}>
<Route path="/" component={App} >
<IndexRoute component={Home} />
<Route path="/game/:id" component={Game} />
<Route path="/game/:id/review" component={Review} />
<Route path="*" component={Home} />
</Route>
</Router>
);
export default routes;
My question is, I want to be able to make GET/POST requests (GET from the Game component to display all reviews from a db and POST to create a new review from the Review component), but where should that happen? I can't tell if it has to happen in my express routes because it seems to me that all express is doing is rendering the static html page and then react-router is taking over after that with handling which components to display.
Any and all help is greatly appreciated.
For the GET request, you can load initial data in a separate function, than load that data in after the component has mounted using componentDidMount like so:
class Game extends React.Component {
constructor() {
this.state = { data: [] }
}
loadCommentsFromServer() {
$.ajax({
....
}
});
}
componentDidMount() {
this.loadCommentsFromServer();
setInterval(this.loadCommentsFromServer, this.props.pollInterval);
}
}
You can do simply have another function for the POST.
I just wanna share my experience, hope it helps. I'm never doing a request on React Route although it can. So, I prefer to perform this action inside component itself on componentDidMount() method, in your case it will be on Game component.
My consideration is to make component reusable, especially if the the component is depends on the request. The benefit when you're implementing request inside the component is your component will automatically call for the request when it mount, wherever you're mounting the component on the route path.
Refers to my experience, you can also make a request on express as server side request, because there are particular condition that need to perform a request handling from server side. Such as handling Cross Origin Resource Sharing (CORS) issue when request to public API from client side, authentication request handling like using OAuth, and more.
If you're request is quite simple, I think request inside the component is sufficient.
Hope it helps. Thank you