[Discussion] Add a 'page' attribute to the RouteObject
See original GitHub issueIt’s fairly common that an app will want to load a particular “page” or scene for a given location type.
This is correctly pointed out in the Medium article where the following example is provided:
Here’s another kind of reducer you’d likely have:
const page = (state, action) => {
switch(action.type) {
case 'HOME':
return 'homeScene'
case 'POST':
return 'postScene'
case 'REPOS':
return 'reposScene'
case 'REPO':
return 'repoScene'
case 'USER':
return 'userScene'
}
return state
}
And its corresponding component:
const PageComponent = ({ page }) => {
const Page = pages[page]
return Page ? <Page /> : null
}
const mapState = ({ page }) => ({ page })
export default connect(mapState)(UserComponent)
// could be a switch (but this is cached):
const pages = {
homeScene: HomeComponent,
postScene: PostComponent,
reposScene: ReposComponent,
repoScene: RepoComponent,
userScene: UserComponent
}
What if we just added a page
attribute to the RouteObject
? Then we could have:
// routes.js
import HomePage from './HomePage.js'
import ContactPage from './ContactPage.js'
const routeMap = {
HOME: { path: '/', page: HomePage },
CONTACT: { path: '/', page: ContactPage }
}
and:
// PageComponent.js
import React from 'react'
import { connect } from 'react-redux'
import routes from './routes'
function mapStateToProps (state) {
return {
pathKey: state.location.type
}
}
const PageComponent = ({ pathKey }) => {
const Page = routes[pathKey].page
return <Page />
}
export default connect(mapStateToProps)(PageComponent)
Thoughts?
Issue Analytics
- State:
- Created 6 years ago
- Comments:16 (8 by maintainers)
Top Results From Across the Web
Can you add attributes to the $route to identify which ... - GitHub
The Route object adds a "method" attribute with values: link, replace, push, go. When the page is not using the vue-router api, ...
Read more >Routing to controller actions in ASP.NET Core - Microsoft Learn
Using page as a route parameter with attribute routing is a common error. Doing that results in inconsistent and confusing behavior with URL ......
Read more >Page Attributes – WordPress.com Support
Go to My Site(s) → Pages in your dashboard; Find the page About and click the title. Locate the Page Attributes module to...
Read more >Managing Route Objects in the IRR - RIPE
Creating route objects for out-of-region (non-RIPE) resources ... mnt-by: attribute of the route object; the mnt-routes: attribute of the ...
Read more >Custom page attribute with Gutenberg | WordPress.org
Hi,. I created a theme few years ago, a one of the features was to display a use custom background color on pages....
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
I believe this would suggest the Flow and TypeScript definitions for
RouteObject
need to be tweaked to include an indexer/ index signature property to allow for properties likerole
.As an aside, is it worth revisiting the idea of maintaining TS definitions in this repo instead of in the DefinitelyTyped repo? DT just seems to add unnecessary friction from both publisher and consumer perspectives. I’ve been noticing a few inconsistencies in the TS definitions while working with the demo app and I would think posting issues in this repo would give the library author and others an opportunity to read and comment on them and might be easier than remembering to tag specific folks in issues submitted in the DT repo.
/cc @valbrand @viggyfresh
Whatup fellas. Nice thread.
I love how you noticed how you can add arbitrary key/vals to your route objects. No changes from the redux-first router are needed to do what you want.
You also could just use the
type
by the way, and maintain a map of types to their component. Or in the code-splitting example’s case, a map from types to scenes. That would keep your routesMap cleaner and representative of actual built-in capabilities. My examples where i switched on a scene or had a map of them was just to make it obvious by using a known pattern. I wouldn’t even build a reducer for this since it’s not needed 😃As for the code-splitting thing, just FYI using
import()
withoutrequire.resolveWeak
won’t work with SSR. It only works for SPAs. But there’s nothing stopping you from using React Loadable or my React Universal Component package. In fact, there is gonna be direct support for prefetching if ur using that package.Also, any day now I’m releasing the async-reactor interface: https://github.com/xtuc/async-reactor
where you can both perform dynamic calls to
import()
and data fetches in the same promise function. You can even callimport()
multiple types. You can also request different things based on props. And that brings us to my main point:you will be able to do this:
./components/MyUniversalComponent.js:
./components/App.js:
…I’m complicating things here since I’m combining 2 concepts: the upcoming react-universal-render package (which helps u resolve combination import()+fetch stateless async components) and redux-first-routing. The former is for a world without redux ultimately.
When using Redux, the
thunk
route option got you covered. I just wanted to show off what was to come 😉But that said, you can still use React Universal Component the old way–i.e. just for chunk imports. And
<Link prefetch href='rudy' />
will be able to prefetch it just like your thunks orchunks
you specify in yourroute
object. There’s a few things I’m trying to work out with it though–namely that if you dynamically import based on a prop. Prefetching must get thefetchProps
to your async promise function.Anyway, I know these thoughts aren’t final or fully clear. I just wanted to let you know that there’s gonna be first-class support for every angle of code-splitting, which means prefetching is a top priority. Also note: ur thunks will be prefetched as part of prefetching ur chunks. This is about to be deployed (hopefully tonight). So basically u can do all the stuff u can do with Next.js minus the framework. That’s one of the primary goals here. And ultimately to do it better with more flexibility, caching, better performance, etc. Ur route objects will get a new
cache
option you can use to provide a function that receives the same state as yourthunk
, so you can produce a cache key from it, and if it’s the same, ur thunk won’t be executed. It will be assumed u cached the result in redux. U can providecache: false
to turn this capability off and manually handle it. And you can not set it, and by default it will hash on the corresponding URL. So if u visit the URL again, the thunk won’t be requested, saving u cycles on ur server and tidbits of perf on clients (no need to have ur app doing stuff it already did).The challenge is tying this into React Universal Component and React Universal Render before I release it. React Universal Component also has a caching feature based on user-provided cache keys. So I’m playing with creating a global cache (
window.ASYNC_CACHE
) that they both can store hashes in (e.g: { ‘some-url’: true, ‘customKey’: true}), and determine if data + imports need to be fetched. Imports will of course only be requested once, since they aren’t dynamic like paths with ids and slugs.Lastly, this may be of no relevance to you–because as i mentioned Universal Render shines in a world without redux state where developers are requesting data ad-hoc in their components. See, this solution requires a virtual-dom-only “pre-render” to resolve all promises recursively (Apollo does this). After which it renders your app again–this time synchronously and quickly getting ur data from a hash map where it’s stored. It’s a minor perf thing, but if u can avoid it because ur Redux-First Router’s
thunk
capability as shown in the SSR docs, u should. That said, if ur using Apollo,Universal.render(<App />)
will also work with Apollo. So all bases will be covered.It will have both a high level api + low level api + mid level usage all covered. But the marketing concept is just
Universal.render()
and not having to deal with all this shit unless u choose to. To me, it has a ring to it.Thoughts are much appreciated. Im on the verge of getting this stuff out and wanna get it right.