Include static HTML folder/files in create-react-app - reactjs

I'm using create-react-app with the react-router-dom module for my React app. I have a subfolder containing static HTML/CSS/JS that I'd like the react app to render. It could be as simple as having the router show /static/index.html.
I've searched around and there doesn't seem to be a definitive answer as to how to so this using create-react-app. Any advice is appreciated.

In order to use routing in your react app, you have to do the following:
Setup
Install react by opening the terminal/cmd, going to the current apps directory, and type in the following command: npm i react-router-dom. Hit enter and let it install.
Next, go to the index.js file, and import BrowserRouter, by adding the following line at the beginning of your code: import { BrowserRouter } from 'react-router-dom'
Then change your render thing to look like this:
ReactDOM.render(
,
document.getElementById('root')
);
What that does, is it basically tells react that App will have routing support.
Now go to your app.jsx file and import the following: import { Route, Switch } from 'react-router-dom';. (I'll explain what they all are later on.)
Now that the behind-the-scenes is setup, we can start adding routes, or paths, to out app.
Apply Routes
Go to your app.jsx file and at the render part instead of just
having components there, let's make a route. (A route just means a
url path.)
You can have components that are always there, no matter what the url path is. In order to do that, just don't have those items as routes. See the example below for more clarification.
To create a route just add the following code: <Route path="/myPath" component={myComponent} />
myComponent will display when the user goes to www.myWebsite.com/myPath.
The problem with this, is say you have a route to /myPath, and a route to / (the home page, i.e. www.myWebsite.com/), then when the user navigates to www.myWebsite.com/myPath, the home page will also display. To prevent that from happening, just wrapp all the routes in a <Switch></Switch> component.
So the final code in the render part of app.jsx will look is like this:
return (
<div className="App">
<div className="bg" />
// Will always show `Header` no matter what the rout is.
<Header/>
<Switch>
<Route path="/about" component={about} />
<Route path="/" exact component={WelcomContent} />
</Switch>
// Will always show `Footer` no matter what the rout is.
<Footer />
</div>
);
Hope this helps. Let me know if you have anymore questions.

Related

React Router not loading correct component

In my app.js file, I have 20 pages listed in the import statements, such as
import NewCars from './New/Cars';
import NewTrucks from './New/Trucks';
import CreateNewSevice from './Service/NewService';
import CreateUsedService from './Service/UsedService';
and so on
in my Route switch I have
<Switch>
<Route path='/New/Cars' component={NewCars} />
<Route path='/New/Trucks' component={NewTrucks} />
<Route path='/Service/NewService' component={NewService} />
<Route path='/Service/UsedService' component={UsedService} />
</Switch>
the issue I'm having is that when I try to link to the UsedService component, it keeps taking me to the NewService Component
On a link on my service page I have the following:
<Link to='./UsedService'>Schedule Service Appointment</Link>
however, it shows the NewService Component, even if I type http://localhost/Service/UsedService, it renders the new service component. The NewService even appears as my home page when I run the app from VS code with npm start. What could be causing this? This is the only component with this issue. I even tried changing the name of the UseService to see if it was a naming convention thing but no luck, still loaded the NewService

How can I statically serve a react app that has routes in it?

I have a website that runs Express on the backend, where I define an api and serve my build directory. My app looks like this:
function App() {
return (
<BrowserRouter>
<Route path="/" component={Home} exact />
<Route path="/explore" component={Explore} exact />
</BrowserRouter>
);
}
I would like to be able to drop the build directory into an S3 bucket then have my API requests to a hardcoded location.
The problem is, when I open up index.html, my and components don't render. What are some possible solutions?
This is a common pitfall of client-side routing, the navigation will work when started from the index, but fail when the users refresh or start their session from another page (for example by clicking on a link).
This is because there won't be any /explore page, since the whole app is bundled in one index.html file.
To make it work you have to configure S3 to serve index.html when it does not find the requested page, by setting index.html as the Error document as explained in this answer.
Try to use a HashRouter instead, like this:
import { HashRouter } from 'react-router-dom';
function App() {
return (
<HashRouter>
//your Routes here
</HashRouter>
);
}
In the S3 Management Console, under Static website hosting, set the error page to be the index.html.

Strange react-router v4 behavior with parent paths

Backstory:
I'm building this simple application and i want to make it have pretty urls with react-router v4.
I've got 3 main components: {Home}, {List}, {Hotel}:
{Home} Component - a simple component where i can select country, datefrom and dateto and route myself to {List}.
Current path example: http://url.com/
{List} Component - A heavy component with a cards full of hotels with links to /hotel/ route.
Current path example: http://url.com/list/country/?datefrom=2019-01-01?dateto=2020-01-01
{Hotel} Component - Most far part of the app, heavy component with hotel information and list of prices split by day.
Current path example: http://url.com/hotel/country/hotel-name/?datefrom=2019-01-01?dateto=2020-01-01
The problem: What i'm trying to do is replace /list/ and use /hotels/ for a {List} component, so i would have somewhat of a hierarchy in url structure.
But once i tried to change /list/ -> /hotels/ for a {List} component route, my whole app breaks and i'm greeted with lots and lots of errors from {Hotel} component, this happens when i try to route myself from {Home} component to {List}.
What i've tried: i've tried to use <Switch> component, it makes {Home} -> {List} route work, but when i try to route myself any further to a {Hotel} component, it actualy render at the bottom of the page and doesn't replace my {List}
Here's my app.js file that gives me strange behavior...
import React from "react";
import { Route, BrowserRouter as Router } from "react-router-dom";
import Home from "./Home";
import List from "./List";
import Hotel from "./Hotel";
import './styles/app.scss';
class App extends React.Component {
render() {
return (
<Router>
<div className="app">
<Route path="/" component={Home} exact />
<Route path="/hotels/:selectedCountry/:datefrom?:dateto?" component={List} />
<Route path="/hotels/:selectedCountry/:selectedHotel:datefrom?:dateto?" component={Hotel} />
</div>
</Router>
);
}
};
export default App;
Hotel and List refer to the same resource, a hotel, but Hotel refers to a single hotel, i.e. is singular, while List refers to an index of hotels, i.e is plural. Usually, routing is done by having a singular and a plural route.
Example taken from GitHub:
URL of a list of commits: https://github.com/facebook/react/commits
URL of a single commit: https://github.com/facebook/react/commit/ec6691a6
In your case it would be:
<Route path="/hotels/your-search-params here" component={List} />
<Route path="/hotels/:hotelId:" component={Hotel} />
Your route definition is not correct.
e.g. take a look at the route path /hotels/:country/:id/:fromDate/:toDate, so a url like this /hotels/usa/123/2019-01-01/2019-12-30 will map correctly to route params and you can access these values in your component like this.props.match.params.id etc. but if you want to take the query params approach then you need to add & sign in between two params like /hotels?country=usa&id=123&fromDate=2019-01-01&toDate=2019-12-30 and then you will access it from window.location.href and parse the query parameters or use npm package like query-params to parse. In this scenario your Route path will be just /hotels

URL with ID not handled by React Router

I'm using React Router v4 in my ReactJs app and looks like whenever I have a path with an ID in it, React Router is not handling it because I see the page refreshing and I'm losing all the data in my Redux store in the process.
Here's my routes section:
<Switch>
<Route exact path="/member" component={Home} />
<Route exact path="/member/accounts" component={Accounts} />
<Route path="/member/projects/profile/:id" component={ProjectProfile} />
</Switch>
Here's how I'm generating the link. This is the link when the user clicks, I see a refresh on my browser.
import { Link } from 'react-router-dom';
... omitted for brevity
const profileUrl = "/member/projects/profile/" + project.id;
<Link to={profileUrl}>Click here</Link>
Other links defined in my routes work fine e.g. home and accounts.
What am I doing wrong here?
Do you pass onClick event handler to the Link component?
If so make sure everything is fine with the handler. You can try to remove it temporarily, in order to debug the refreshing.
Credits:
https://stackoverflow.com/a/46115304/4312466
https://github.com/ReactTraining/react-router/pull/4066#issuecomment-383910759
After a lot of testing, I found the cause. We must use NavLink or Link from react-router-dom whenever linking to a component.
I noticed I wasn't consistent in using NavLink in my app. Instead I was using regular
<a href={myModuleUrl}>Module Name</a>.
Once I switched to using NavLink, it worked as intended.

React router 4 - Why is my component only rendered on manually setting the url but not on clicking a Link with same url?

I started using react router v4 and I have 2 questions. Ive been researching and reading about router 4 but cant explain why the following happens:
ps. I have included only code I thought is relevant, please let me know if I should dd more.
<BrowserRouter>
<div>
<Route path="/" component={PostsIndex} />
<Route path="/posts/new" component={PostsNew}></Route>
</div>
</BrowserRouter>
PostsIndex:
<Link to="/posts/new">Add a Post</Link>
1. What happens with my code below is on route '/' I am being shown PostsNew Component. When I manually put url to '/posts/new' both components are being rendered - PostsIndex and PostsNew which is intended. HOWEVER, when im on '/' and click on my Link (with path: /posts/new) nothing happens. The PostsNew component is not being rendered unless I refresh the page (so the url already changed after I click the link but I need to refresh it-url stays same- and only then will the nested component being rendered). Why does this happen?
Another question:
Below I want to achieve the opposite- NOT nesting routes. When I use switch and put the most specific route first, it works. Also when I click on the Link, the PostsNew is being rendered without the need to refresh. My question is just to understand routing better:
I would expect in my code below, both components being rendered on /posts/new - but here the PostsNew component is NEVER being rendered. Why?
Why is my Link working when I use Switch and if I dont I must manually refresh/put url? Thanks!
If you only want a specific path to render you need to add an exact attribute to the Routes:
<Route exact path="/" component={PostsIndex} />
<Route exact path="/posts/new" component={PostsNew}/>

Resources