Import external static liquid.html file into react - javascript

I have this below file saved as bbox.liquid.html in my public folder.
File : https://github.com/aws-samples/amazon-sagemaker-ground-truth-task-uis/blob/master/images/bounding-box.liquid.html
My goal is to either import the file as react component or redirect to the page and show it to user.
Method 1. import the file as react component
I tried this all answers, but its not working.
Method 2. redirect to the page
I tried to redirect it using router in app.js, after clicking it I see a empty page.
<Routes>
<Route exact path="/" element={<Home />} />
<Route path="/about" element={<About/>} />
<Route path="/bbox/" element={<Navigate to = {"/bbox.html"} replace />} />
</Routes>
[info] index.tsx:30 No routes matched location "/bbox.html"
Note: once after a reload it shows the expected page.
It would be great I get any working mechanism for method 1

Related

React - TypeError: Cannot read property 'push' of undefined, already exported default withRouter

I have a page component SimulationReport that I want to redirect to upon clicking a button from the Reports page component. This is the App component with the Router:
function App() {
return (
<React.Fragment>
<Router>
<NavigationBar />
<Sidebar />
<Switch>
<Route exact path="/" component={Ratings} />
<Route path="/LeagueSettings" component={LeagueSettings} />
<Route path="/Fixtures" component={Fixtures} />
<Route path="/Reports" component={Reports} />
<Route path="/SimulationReport" component={SimulationReport} />
</Switch>
</Router>
</React.Fragment>
);
}
And here are the relevant code bits from Reports which is a function component:
import {withRouter} from "react-router-dom";
<td>
<Button variant="primary" onClick={handleSimView(index)}>
View
</Button>
</td>
const handleSimView = index => e => {
console.log("index: " + index);
loadSimulationResult(simulationIds[index]);
props.history.push("/SimulationReport");
};
And at the end of the file I have this:
export default withRouter(Reports);
Upon clicking the button, I receive this error:
TypeError: Cannot read property 'push' of undefined
I'm not sure what I need to do to redirect this? Or maybe I should be doing it a different way?
Seems that your prop history is not being passed from the <Route> tag in your component.
You can pass props to a Route Rendered Component by doing the following line:
<Route
path='/SimulationReport'
render={(props) => <SimulationReport {...props} history={yourHistoryObjectForTheRouter} />}
/>
where yourHistoryObjectForTheRouter would be your custom history exported object.
EDIT: Updated code
UPDATE TO ANSWER TO ADDRESS OP's NEEDS:
1° Alright, so first you'll need to install the package called history to your React Application. (You can use npm i history or yarn add history. It depends on what you have installed. If you don't know what's yarn then use the npm option)
2° Somewhere in your project inside the App folder (src/App/), you're going to create another folder called history and inside index.js.
The contents of the index.js file are going to be the next ones.
import { createBrowserHistory } from 'history';
export default createBrowserHistory({});
3° Once that is done, head to your App/index.js file, where you have your <Router> main tag. If you've done everything as I stated before, in that App/index.js you're going to add a new import:
import history from "./history";
Which is your new Custom History Object.
Here you can choose two paths of how you want to solve your problem
=== First Solution
4° Scroll down in that same file, until you find your <Router></Router> tag, and you're going to update it to this next part:
<Router>
<NavigationBar />
<Sidebar />
<Switch>
<Route exact path="/" component={Ratings} />
<Route path="/LeagueSettings" component={LeagueSettings} />
<Route path="/Fixtures" component={Fixtures} />
<Route path="/Reports" component={Reports} />
<Route
path='/SimulationReport'
render={(props) => <SimulationReport {...props} history=
{history} />}
/>
</Switch>
</Router>
After this, you'll have your Custom History Object setted up and your component now should work.
This solution however will only work for that specific component Route, and that means that you will have to do the same for the other <Route > that require the use of the history object.
Stop here if you choose this solution.
=== Second Solution
This solution is better, because you'll now have access to your history object globally, just with an import.
4° Scroll down in that same file, until you find your <Router></Router> tag, and you're going to update it to this next part:
<Router history={history}> //Here's the change
<NavigationBar />
<Sidebar />
<Switch>
<Route exact path="/" component={Ratings} />
<Route path="/LeagueSettings" component={LeagueSettings} />
<Route path="/Fixtures" component={Fixtures} />
<Route path="/Reports" component={Reports} />
<Route path="/SimulationReport" component={SimulationReport} />
</Switch>
</Router>
After this, you'll have your Custom History Object setted up.
5° Navigate to the file that contains the Reports functional component, and on the imports at the top of your file, you're going to import the same history as you did in App/index.js. Beware that depending on the level of subfolders that your Reports components is in, it's how the import is going to change. It can end up like this:
import history from "../history";
or this
import history from "../../history";
it depends or even more "../". It depends on your subfolder levels
After that, you'll need to update your function handleSimView so instead of doing this:
const handleSimView = index => e => {
console.log("index: " + index);
loadSimulationResult(simulationIds[index]);
props.history.push("/SimulationReport");
};
do this:
const handleSimView = index => e => {
console.log("index: " + index);
loadSimulationResult(simulationIds[index]);
history.push("/SimulationReport"); //Change is here, removed "props."
};
After this, your code should work. This solution you can implement it everywhere as you would only need to import the history object and just use it.
I'll be waiting to hear from you to see if it worked. If anything else happens, you can ask me.

Can I use react router in django project?

I have a project that uses React in frontend and Django as backend.
Also I use react router in my project and the code looks like this:
<BrowserRouter>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/teachers" exact component={Teachers} />
<Route path="/courses" exact component={Courses}/>
<Route path="/about" exact component={About} />
<Route path="/posts" exact component={Posts} />
</Switch>
</BrowserRouter>
In django my urls file looks like this:
urlpatterns = [
path('', views.index, name="index"),
]
The problem is that whenever I try to navigate to the page from react router I get 404 error from django.
Dude I am having the same problem. From I have researched the answer is actually to throw a catch all at the end of your urls in django. I can only find the old way of doing it.
url(r'^(%s)?$' % '|'.join(routes), TemplateView.as_view(template_name='index.html'))
I am not sure how to do it with path but I had found it earlier. It might be
re_path(r'.*', views.index)
Just let me know if that works so I can go home and use it :)

How to get parent parameter in nested route?

I have the following basic structure of nested routes/components for a react app:
/users -> UsersList
/users/:id -> UserLayout
/users/:id/ -> UserProfile
/users/:id/settings -> UserSettings
/users/:id/blah -> YetAnotherComponent
What I'm trying to figure out, in the context of react router v4, is how to access the :id parameter in the UserSettings component. I can access it fine in the UserLayout component, but nowhere else further downstream.
My main router definition lies in a Home component, but all the user-specific routes contain the same header information so I want all the user-specific routes to be nested. My current structure has these nested routes defined in the UserLayout component. However, no matter what I do to the layout component's route definition, I cannot get any other route than the "index" route (UserProfile) to render. When trying to access UserSettings or any other route, my top level 404 route gets hit instead.
Here's the relevant JSX (snippets of the actual components' render functions):
Home
<main>
<Switch>
<Route exact path="/login" component={Login} />
<Route exact path="/users" component={UsersList} />
<Route exact path="/users/:id" component={UserLayout} />
<Route exact path="/" component={Home} />
<Route component={NoMatch} />
</Switch>
</main>
UserLayout
<div>
<Switch>
<Route path={`${match.url}/settings`} component={UserSettings} />
<Route path="/users/:id/blah" component={YetAnotherComponent} />
</Switch>
<Route path="/users/:id" component={UserProfile} />
</div>
In the UserLayout component I've tried both path formats shown in the Switch and have tried turning on/off exact matching. The only thing I can come up with is using the Route component's render parameter to pass the id parameter, but that just seems wrong. Is that my only option?
Of course only a few minutes after I post, I figured it out. In my top-level route config, I had set the /user/:id to require an exact match. This meant that when I navigated to /user/:id/anything_else react router didn't load UserLayout at all and thus didn't get the chance to test the remainder of the routes I had configured.
So I changed this from my home component:
<Route exact path="/users/:id" component={UserLayout} />
...to this:
<Route path="/users/:id" component={UserLayout} />
... and now all is well with the world.

Serve another(standalone) page or static file in website built with react

I have a website built with react, which uses react-router. For some route I want to serve another page or static file, but since all request are forwarded to react router, its doesn't work.
for example
www.myapp.com/sitemap.xml
www.myapp.com/something.html
^ these link works first time, but once i load website then it doesn't work, as all request goe through react router.
Any solution to make it work all the time. Thanks.
Edit
I'm using apache server which is configured to redirect all request to index.html, i guess this is the reason for this behaviour. This is my configuration, but i don't know how to fix this.
Options -MultiViews
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]
Update
I tried solution suggested in answer.
my routes looks like this, for something.html i am loading ServerLoad component
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/about" component={About} />
<Route path="something.html" component={ServerLoad} />
<Route component={NoMatch} />
</Switch>
In ServerLoad component's componentDidMount function I did this. But it doesn't work.
componentDidMount() {
window.location.reload(true);
}
More
I have setup this project using create-react-app, and serving it by express server(like this). I'am not sure if i need to do some setting there to server other static files.
This should work:
const reload = () => window.location.reload();
<Router>
// all your routes..
...
// Your special routes..
<Route path="/sitemap.xml" onEnter={reload} />
<Route path="/something.html" onEnter={reload} />
</Router>
So, I think this should be pretty clear what it does ;)
Update:
if this is an option you can simply put target="_blank" attribute in your <Link>
IMHO this is from the UX perspective even better, because if these routes are not part of your main application, the user can just switch the Tab after visiting that special pages.
How about simply put your statics files like sitemap.xml inside React's public folder along side index.html.
I thinks this is the easiest way.
It's an unwanted behaviour of ServiceWorker.js use the comment below and change it in index.js of your React project (if you don't need a service worker) and it should work
import { unregister } from './registerServiceWorker';
unregister();
https://github.com/facebookincubator/create-react-app/issues/2715
If you still need a service worker and you want to avoid it having this behavior, consider installing a custom service worker, there you can establish a whitelist of paths to be ignored. For more information you can check the next link.
https://medium.com/swlh/how-to-implement-custom-service-worker-in-create-react-app-without-eject-bfa2c5f4ae96
Use Switch combined with a NoMatch component, combined with webdeb's solution:
<Router>
<div>
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/admin" component={Admin} />
<Route component={NoMatch} />
<Route onEnter={() => window.location.reload()} />
</Switch>
</div>
</Router>
This will match routes, show 404 if no valid href exists, and show a file or something if it's a valid href.
If you need /terms to redirect to /terms.html, the code below worked for me with react-router 3.x.
const reload = () => window.location.reload();
<Router>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/terms.html" render={reload} />
<Route path="/privacy.html" render={reload} />
<Route path="/terms" render={() => <Redirect
to={{
pathname: "/terms.html"
}}
/>}
/>
<Route path="/privacy" render={() => <Redirect
to={{
pathname: "/privacy.html"
}}
/>}
/>
</Switch>
</Router>
1. Create folders for each HTML file inside the public folder.
2. Add route paths (path= name_of_folder_contained_static_file)
3. Call route paths as you want :)
Demo:
If the pages are unrelated to the Reactjs App at all(i.e. using another directory), I think we can route it from Node layer using the following code, so that the structure is more intuitive:
app.use('/url_to_static_pages', express.static('path_to_static_files'));

Can't make React-Router render two different components, always render root

I have these two components that are completely independent of each other. I want to render App when I enter / and render About when I go to /#/about
I got this piece of code (but I tested quite a few others):
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, Link, browserHistory } from 'react-router'
import App from './App';
import About from './About';
ReactDOM.render(
<Router history={browserHistory}>
<Route path="/" component={App} >
<Route path="/about" component={About} />
</Route>
</Router>
, document.getElementById('root')
);
I also tried something like
<Route path="/about" component={About} />
<Route path="/" component={App} />
And changed /about to /#/about, about
But it always render the "fallback" /, it always goes to this route, no matter what.
How can I make this app navigate properly to / and /about and render the App and the About components?
#edit
Assuming that my About component is broken, I removed the first Route and kept only the /about (kept only the /about Route) :
<Route path="/about" component={App} />
(I tried keeping About as well in a previous test) and also changed the /about to about and /#/about.
And I get this error on console:
"VM3651 bundle.js:30801 Warning: [react-router] Location "/#/about" did not match any routes"
#edit 2
I made a change, following the example #Dominic posted. I had to make some modifications to make sure both components would render. I added the {this.props.children} to all Components to understand what would happen.
//imports
ReactDOM.render(
<Router history={browserHistory}>
<Route path="/" component={About} >
<IndexRoute component={App} />
<Route path="/about" component={Other} />
</Route>
</Router>
,document.getElementById('root'));
The route http://localhost:3000/#/about is rendering:
> About > App
So it is rendering the IndexRoute, it is not getting caught by the /about.
And this is now exactly what I need, because I didn't want a root component, I wanted 2 routes to 2 different and isolated components. I need something like two sibling routes.
#edit
The About.js
import React, { Component } from 'react';
class About extends Component {
render() {
return (
<div>
About page
{this.props.children}
</div>
);
}
}
export default About;
Solution:
Since I'm using a HASH (#) in the URL, I should use hashHistory from React Router in the <Router history={hashHistory}>
You're confusing how routes work - About is a child of the App route, so in order to render About, it has to render App.
In other words your App component is the "shell" and all components under it render INSIDE it (via props.children).
You should add another route to render /.
import { ..., IndexRoute } from 'react-router'
<Route path="/" component={App} >
<IndexRoute component={Home} />
<Route path="about" component={About} />
</Route>
Your App does not contain route specific content, it would be something more like this:
<div id="app">
<nav>app navigation</nav>
<main class="route-content">{props.children}</main>
</div>
Docs: https://github.com/ReactTraining/react-router/blob/master/docs/guides/RouteConfiguration.md#adding-an-index
Those routes look correct to me. Are you getting any errors in the console? Maybe your About component is undefined and thus not rendering. Can you post your About component?

Categories

Resources