react-router-config - multiple path for one component - reactjs

I use react-router-config package from here: https://www.npmjs.com/package/react-router-config for my project. I created a Routes.js file where I set my routes configurations, it looks like this:
export default [
{
...App,
routes: [
{
...IndexPage,
path: '/',
exact: true
},
{
...CategoryPage,
path: '/computers'
},
{
...CategoryPage,
path: '/home'
},
{
...NotFoundPage
}
]
}
];
as you can see I use two paths '/computers' and '/home' to load the same component CategoryPage. I wonder if it possible to pass multiple paths in one object to load the same component, something like this:
{
...CategoryPage,
path: ['/computers','/home']
}

base on the documentation https://github.com/ReactTraining/react-router/blob/v3/docs/Glossary.md#path
path type is a string but when I read this update, I guess it's support for react router version 4.4
[https://reacttraining.com/react-router/web/api/Route/path-string-string][1]
In this example
<Route path={["/users/:id", "/profile/:id"]} component={User} />

For some reason, I think the way you wrote might be the way. You could first create your ideal structure, ex.
{
components: [...CategoryPage],
path: ['/computers','/home']
}
And then use your own utility function to transform it into your final structure. This way you can make your routing structure as flexible as you want and one source of data at the same time. I found thinking this way is more scalable than bending the routing default structure.

Related

Routing query params without slash before it in react-location

Previously, I was using react-router-dom. With react-router-dom, I could define a route with query params like this:
<Route path="/p:productId" element={<Products />} /> // localhost:3000/p1 will match this route
But it seems like react-location doesn't work in the same way. The only way that I found is by defining the query params as a child of another route, but this leads to a slash before the actual letter 'p'.
The following example comes from the official documentation, but I'll rewrite it to match our own example.
const routes = [
{
path: 'p',
children: [
{
path: ':productId', // matches /p/:productId . localhost:3000/p/1 will match this route.
},
],
},
]
Is it possible to make it like the first example, which comes from react-router-dom?
Regardless of the answer, is it a bad practice to do it like the first example?

Generate Route dynamically - React

I am trying to do RBAC(Role-Based Access Control) using react js. I have seen some related question on Stackoverflow but they are not related whith my question. My question is:
There is a user and the user has a role and every role has its own list of menus assigned to it. Each menu has a path and component name.
What I need to do is that when a user sign in Route will be generated dynamically based on his role.
As we know the following is the normal way of defining routes in React. and it is static.
<Switch>
<Route path="/users" component={Users} exact />
<Route path="/items" component={Items} exact />
....
</Switch>
I need to generate every Route dynamically. This is what I have tried,
menus=[
{
name:"Users"
url:"/users"
component:"Users"
},
{
name:"Items"
url:"/items"
component:"Items"
}
]
<Switch>
{
menus.map(menu =>{
return(<Route path={menu.url} component={menu.component} exact/>)
})
}
</Switch>
But this is not working for me. When I try to navigate to /users it can't find the route. But when I use the first method it works correctly. Can you please tell me whats wrong with my code??
Here is a sample code that describes my problem
Here is a sandbox link
You are passing the component as a string to Route, you need to remove the quotes around them in your menu array.
menus=[
{
name:"Users"
url:"/users"
component:Users
},
{
name:"Items"
url:"/items"
component:Items
}
]
If your menu is dynamic from a DB and they are strings, then you will need to make sure the component is imported into the file, and then map it with an object like so:
import {Users} from './Users';
// assuming this is what menu will return as
const menus=[
{
name:"Users"
url:"/users"
component:"Users"
},
{
name:"Items"
url:"/items"
component:"Items"
}
]
const keyMap = {
Users: Users // mapping 'Users' string to <Users/> component
}
return (<Route path={menu.url} component={keyMap[menu.component]} exact/>)
Solution demonstration is available here

React routing between static and dynamic pages

So normally our S3 hosted Web app index.html looks like:
<div class=app></div>
That also references the JS bundle & which React renders to and that's fine. But some elements of the site are statically generated for speed & SEO and look like:
<!-- dynamically generated content -->
<div class=app></div>
<!-- statically generated content -->
<h1>Title</h1>
<p>Information, blah blah blah</p>
<p>Lots of content</p>
Conventional wisdom might suggest having the static stuff in a ReactJS component and then reactDOM.renderToString(), but I don't want to do it that way since it's rather complex to do it that way since the static component pulls from many several APIs.
So I am struggling to find documentation for what I want. I want to be able to say for certain URLs, that a full page load is necessary (window.location). Similarly, when navigating away from a static page with content, a full page load is needed or the content need to zapped back to <div class=app>.
How do I achieve this with a react router?
this is something I would go with off the top of my head. I apologize if doesn't suit your needs/purpose. I think I understand what you are going for. I might have this wrong, but I am thinking that your static pages do not have react-route on them. Literal static pages, outside the react environment.
I'd create a whitelist for these static pages.
const whitelist = ['aboutus', 'help']
then in my routes, I'd have the fallthru, check for the path.
//psuedo code
{
path: '*',
onEnter: () => {
if(whitelist.includes(path)) {
window.location = /path
}
},
component: Four0Four,
},
or you could just prepend the static pages like so:
perhaps a url like "/static?aboutus.html"
//psuedo code
{
path: 'static',
onEnter: () => {
if(whitelist.includes(path)) {
window.location = `/static/${param}`
}
},
component: Four0Four,
},
When you come back to the "react-route react" app, I wouldn't think you'd have to do anything as the react-router will pick up from the url you move back to.
You could also use the "Listener" on the location event.
browserHistory.listen(location => {
// do your checking for the static pages here
});
I hope I am not too far off base on my interpretation, if I am. Let me know and I'll delete my response.

Can't pass relative img src route in React + Webpack

I can't dynamically pass relative img src route in React + Webpack with this.props.
This is a very simplified part of the parent component. It iterates some data list and generates ImgComponents passing props. Here is only tiny part of it:
return (
<div>
<ImgComponent srcProp={videolist.anotherImage.src} />
</div>
);
The ImgComponent has:
render() {
return (
<div>
<img src={`${this.props.srcProp}`} />
</div>
);
}
In console I get exactly the same route as i pass with this.props.srcProp, but it would not find the folder and the img there. As if webpack does not load the img.
Here is the console:
<img src="framework/assets/images/cover-bigbuckbunny.png" class="_2WcF9ZmcK-9bQX6jKk18Y_" data-reactid=".0.1.1:$comedy.0.0.$0.0.0.0">
No matter what route i indicate, the img is never found in the folder.
Here is the webpack config for png:
{ test: /\.png$/, loader: "url-loader?mimetype=image/png" }
BTW. It works fine if i require the file, like:
<img src={require ('framework/assets/images/cover-bigbuckbunny.png')} />
or indicate some remote route, like http://route.to.some.img
Seems like webpack does not load it. What should i do to dynamically load local img files by dynamically passing src with {this.props.src} ? As I can see, the loader loads img fine if i indicate the file with require. But this way i cannot do it dynamically, as require does not take variables.
What I managed to do is to require('../../assets/images/myFirst.img') in the object, containing the routs to the locally stored files:
in playlist.js
export default (
{
cartoons: [{
images: {
poster: require('../../assets/images/myFirst.png')
},
streams: [{
type: 'mp4',
url: 'http://media.w3.org/2010/05/bunny/movie.mp4'
}]
});
Then I work with this list as with any object:
import playlist from '../../playlist';
and iterate this object in a usual manner. The image will be there.
Webpack will not traverse your code to find and convert all possible references to files.
Consider following code:
<img src={'/foo/bar/baz.jpg'} />
It is your responsibility (perhaps using a build target) to ensure that baz.jpg is copied into the foo/bar directory under your web app root.

Aurelia: two templates added, second 404's

I'm trying to set up multiple templates in Aurelia. Currently, I have two custom templates. No matter what I do, I am only able to load the first one I add. The second returns a 404.
For reference, here's my setup
AureliaFile:
var aurelia = require('aurelia-cli');
aurelia.command('bundle', {
js: {
'wwwroot/app-bundle': {
modules: [
'resources/main-content/main-content',
'resources/side-menu/side-menu',
'resources/index',
'main',
'app',
'aurelia-framework',
'aurelia-bootstrapper',
'github:aurelia/loader-default#0.9.0',
'github:aurelia/templating-binding#0.13.0',
'github:aurelia/templating-resources#0.13.0',
'github:aurelia/history-browser#0.6.1',
'github:aurelia/templating-router#0.14.0'
],
options: {
inject:true
}
}
},
template: {
'wwwroot/app-bundle': {
pattern: '**/*.html',
options: {
inject:true
}
}
}
});
main.js:
export function configure(aurelia) {
aurelia.use
.standardConfiguration()
.developmentLogging()
.plugin('./resources/index');
aurelia.start().then(a => a.setRoot('app'))
}
my resources folder (where my two templates are) looks like:
resources
index.js
main-content
main-content.js
main-content.html
side-menu
side-menu.js
side-menu.html
and finally, my index.js is:
export function configure(aurelia) {
aurelia.globalizeResources("./side-menu/side-menu");
aurelia.globalizeResources("./main-content/main-content");
}
i have also tried changing it to:
export function configure(aurelia) {
aurelia.globalizeResources(["./side-menu/side-menu", "./main-content/main-content"]);
}
Now, my problem description
No matter which I add first in my index.js, the second is not loaded. After I run aurelia bundle, and load the site in the browser, I see:
if i switch the load order, the other template 404's. If I include only one template in the index.js, the site loads fine, albeit without my second template. Can someone please give me a pointer as to what I have missed?
Apologies for the long post, I wanted to give as much information as possible.
To add more description, in my Aurelia-built appbundle.html and appbundle.js, I see both templates, they look 100% correct as far as i can tell.

Resources