Redux-First Router lookin Sexy on Code Sandbox
This article could have just as accurately been titled: “How to use Redux-First Router on Code Sandbox,” but hey, when something is sexy, in the words of Bruno Mars, flaunt it.
First off — and with nothing but thankfulness— the response to Redux-First Router has been overwhelmingly “that’s how it’s supposed to be!” Here are some quotes:
- “This is genius.” BerkeleyTrue (CTO of freeCodeCamp)
- “Just finished ripping out react-router and using this in its place…so far so (very very) good.” -Vignesh Venkataraman
- “It’s been a while since I read anything as well written in routing land. It’s a really exciting idea and I want to try it and port my rcn.io to it.” -Restuta
- from our first major Pull Request: “Happy to contribute. Your blog post + what the formidable guys wrote really resonated. This is the router now. Thanks for being super responsive on this. Always makes the PRs so much more fun 👏 🍻” -@iansinnott
- “First time I’ve seen redux make sense!” -Eric Clemmons
- “first I want to say fantastic work on all of your libs for react + ssr + code splitting — doing myself a deep-deep dive the last several days to get something correctly started, and I came across all of your stuff today and it’s been a godsend.” @eudaimos
- “First off, this is great work — thanks for making this! I’m so happy to have everything in Redux.” @bmoquist
Lots of “firsts” for Redux-First Router…SIDE NOTE: feel free to go straight to Code Sandbox if you’re the “power user” we know you are (and that my tools target).
You know what they say: “don’t brag about it, show me.” And that’s why RFR + Code Sandbox is a sexy combination. So let’s get down to business on some things you can do in Ive’s and Bas’s kick-ass playground, and where to start.
Oh, yea, you can start right here:
Embeddable code widgets. Sexy! That’s not a photo folks.
You can also go directly to the homepage. Ives (one of Code Sandbox’s 2 creators) was supportive enough of the movement to put RFR directly on the homepage. I worked directly with him on several issues just to get this functioning flawlessly, and he was more than accommodating and super fast. He’s a superstar in the making. Do not sleep on him. But I think you already know that. 🔮
Back to the goods (5 things to tinker with in the Sandbox)
1. DATA-FETCHING — src/routesMap.js
thunk key. That’s the most valuable option on each route, and the topic of the 1st thing to tinker with. If this is your first time looking at this, you probably should read the acclaimed intro article (hey, other people said it) on Redux-First Router:
The purpose of this article is to debunk the effectiveness of route-matching components + nested routes when using…medium.com
The summary is that action types (
VIDEO) are the keys for routes in your
routesMap. You don’t dispatch an action that is always the equivalent of a
PUSH action (not very useful) like in previous redux-specific routers. Duh.
Let’s keep it moving.
So you have a
routesMap like in every MVC that ever existed.
Everything old is new again.
- And actions are your routes
- Path parameters are extracted into a payload object
- The thunk is the same thing you dispatch to the
no new concepts
Just, here, it has far more context since it’s attached to a route. What you’re seeing here is the initial route action being dispatched (which you can use to trigger spinners etc), paired with a “follow-up”™ asynchronous action that a few moments later will dispatch your data. In this case we dispatch an array of videos and its category.
In a future article, I’m going to go into detail on data-fetching, but the overall idea is you can finally write Redux apps that don’t have to worry about the URL while providing the simplest solution for your 80% use case. In fact, with the URL off the table, it leaves a lot of breathing room for your primary task of data-fetching.
That’s all on that subject for now. Think of this article as more of a montage/preview of what’s inside the RFR Code Sandbox.
apps dont gotta think about the URL! The way it’s supposed to be! — me
“EXACTLY.” — Eric Clemmons
Data fetching complete. Read the code (look at the above picture). It’s my artistic day. Can’t you tell by my ability to steal CodeSandBox’s color scheme.
2. Trickle-down hashing for great justice — components/Switcher.js
WTF is “trickle-down hashing”? It’s a new professional term for keying into objects at multiple consecutive places in your architecture to display what you need. And with the same key, saving you from writing imperative 3–12 liners you’ll have to figure out at a later date.
What do I mean? Look at the next screenshot.
I don’t claim any of this is advanced science. I just claim with a few puzzle pieces that have long been missing, you can avoid actual work at multiple levels. And not because you’ve succumbed to an automagic solution that is great in the short term, but rather, because when multiple solutions correctly invert control flow, stars align. 🌠 🌠
This isn’t a framework that turns out to be a major head-ache as you resolve to a million workarounds to achieve custom needs. It’s essentially a configuration-driven middleware backing a “frameworkless” approach I recommend for “power users.”
So I want you to check out the
<Switcher /> component ☝️ in src/components/Switcher.js, as well as the reducer that powers it: reducers/page.js .👇🏿
Through the one
page reducer, we are able to:
- extract a page from the URL via an action type
- set a dedicated state named after it in the reducer
- then here’s where it really comes together: declaratively tell a React Transition Group-based component what page should currently be visible (while getting sexy transitions)
- and then do the same thing with
react-universal-componentnested within it, which code splits and fetches the necessary component.
If you never used React Transition Group, honestly you’re missing out. It’s been an extremely underrated underused tool in my opinion. As I recall there are articles out there describing how people hate it. I think it’s one of those things where people just felt it wasn’t fancy enough or never truly groked it. Truth is the concept was right, but it was problematic and the vision was never completed. So I made my own. It’s called
TG applies css and gives you callbacks. It lets you apply global props to all transition children, and it lets you customize individual children. It has a few other highly useful features like debounce.
What I say to people is this:
“If you don’t have dynamic animations, you should be using CSS for the best frame rate.”
TransitionGroup is great at that. That’s a topic for another time. It‘s not a big deal — and that’s the point, none of my solutions are.
My solutions are the simplest to-be-expected interface that wasn’t previously possible because of various implementation hurdles that none of us had the time to work on. But the interface to all this stuff is stupid simple. Don’t let it fool you though into thinking because it’s not complicated enough it’s not the one true way — a typical developer trap.
Transition groups are powerful in that they let you circumvent the challenge of managing multiple overlapping animating components. Magically it lets you think in terms of one visible component at a time.
Here Universal Component shines as well. It switches in and out components, just without the animation. Its speciality — if you’ve been following my beat — is universal rendering. That means not just client-side
import(), but successful synchronous rendering on the server, which can be seamlessly passed off to the client [via webpack-flush-chunks]. BIG DEAL! In this particular case on Code Sandbox we’re just making use of the client-side capabilities.
but hey, u follow this pattern using these tools and SSR is back on the menu.
So in Summary, we have this:
- the action type is the name of the component you want to display
- the page reducer state contains the name of that component
<TransitionGroup />keys on that same page name to declaratively show 2 components during transition without you having to manage the temporary overlap
universalHOC again keys on the page name to handle all the dynamic importing needs you might have (notice that
import()is called with a dynamic template literal:
And that’s why I call it trickle-down hashing. Or keying. Or whatever you wanna call it. One key used at 4 levels “for great justice.”
I don’t know the etymology of that phrase by the way. I honestly have been grinding so hard for so long I missed the backstory on a great many things that weren’t mission-critical over the years. But I take it that term has been around for a while, and comes from a non-native english speaker, maybe France (I like the the electronic group Justice by the way — a lot). Either way, the concept of stupid simple things “for great justice” resonates with me. Justice is what we need after all, after banging our heads against keyboards for so long.
3. NEXT: REDIRECTS — src/options.js
Yes, like your favorite server-side MVC framework from 2007 to 2011, you can filter at a designated stage. That stage is called
onBeforeChange. Once this reaches past “Pre Release” that will be deprecated and be renamed
onBeforeAction. Why? Same reason route thunks are called
Terminology matters. Familiarity matters. Not having to learn new concepts MATTERS. This shit is hard and time consuming. RFR aims to introduce as few concepts as possible. And generally to be a natural extension of Redux — the most useful piece of software (pattern) ever invented FOR ME.
Disclaimer: in everything I write and make I’m basically just telling my story. Not telling u how to do it. But describing and sharing what has worked FOR ME. So if it resonates with you, awesome.
The way redirects work is you import an action creator named
redirect from RFR (it’s basically our only action creator you get by the way, as a primary goal has been to keep the API surface to a minimum). But this action creator was necessary. So you simply pass it the typical action you dispatch to go to a route like this:
redirect(action). You know, the routes that have a
type in the
routesMap. But this is tagged as a redirect.
When it reaches the middleware, everything short-circuits and a different actions is dispatched. Other things happen as well — for example, client-side the history is replaced rather than pushed (so that user’s don’t end up in an infinite human loop of pressing the back button over and over), etc.
So open up src/options.js and see how a redirect is performed under a certain condition (aka filtering) in
onBeforeChange. Again, the filtering is the sorta stuff you used to do in “controllers” in your favorite MVC. If you’re new to the game — well everything old is new again, you just don’t know it. So
onBeforeChange and RFR in general are the C in MVC, whereas React is the V and Redux the M.
Have we really been missing the “C” all this time just to get back to MVC?
The condition in this example is
isAllowed. It’s a function that gets passed the user state (which of course
onBeforeChange has access to since it’s signature is pretty much the same as a
thunk. It takes the user and the current type (aka page, aka route) and checks the user’s roles, and checks the roles the current page/route/action is targeted toward, and if it all matches, lets the user in.
onBeforeChange gets a 3rd argument (after
action. The reason is because the state hasn’t changed yet, but we know the action. So you need to use the action in this case to determine what the state will be, and if in that state the user is allowed to coexist. The routesMap happens to be stored in state — so that’s one of the many things you can get from
getState at this critical juncture that isn’t dependent on the next state — which is why it’s still important to get passed
getState, not just the action.
And like all good Redux tools, it promotes purity since you don’t gotta get the routesMap from global state. It will all make sense once you start using RFR. But take my word it’s the natural way this stuff should be happening.
who takes anyone’s word in the precarious profession called software development anyway?
4. THUNK-LEVEL REDIRECTS
You can also redirect at the thunk level. I.e. for an individual route. SSR will resolve this by the way. It’s all built-in. You can also dispatch
NOT_FOUND (you’ll see in the Sandbox). That’s an action type exposed by RFR when you just don’t know what to do, but you know you don’t have the data needed to show the current page/components. Your reducers can respond to it. RFR’s
location reducer will respond to it. And therefore your components can easily respond to it. You will also receive this action type when the user visits a URL there is no route for, or if YOU dispatch an action there is no matching path for.
There’s some nuances to this. The primary one is: well, what URL will show in the address bar? Well, it depends — did the user try to directly visit a URL that your routesMap just doesn’t handle? In that case, the URL stays the same, like if you visited a non-existent github repo. But if you dispatch an action with no matching route, well, there’s a fallback URL you can specify as an option called:
notFoundPath. And under certain conditions it will just keep the same URL. Read the docs for these nuances.
5. GENERAL ACTION-TO-REDUCER STUFF
So yea, if you know how to use Redux, you know how to use RFR. Your payload has params extracted from dynamic path :segments. You now have informational types — as you know from the RFR Pre-Release article, which describes how just dispatching a type for
history.push is a missed opportunity. A missed opportunity that RFR nails, might I add :)
Some things to do:
- Checkout how the
playingreducer simply returns true if the
action.type === ‘PLAY’. I mean you can do whatever you want in here — you’re going to forget URLs are even powering this.
- More importantly look into the
videosByCategoryreducer (pictured above) which essentially knows to show a spinner when the current category (extracted from the URL) has no videos for it. It’s all natural. A “follow-up” action in the route thunk fetches the data.
By the way we’re going to get into the significance of the simplicity of a single thunk paired to a route in my next more serious RFR article. The hint is:
We’re doing too much and making our lives miserable through the flexibility of fancy middleware (sagas, observables, and even ad-hoc thunks) when most of the time you’re just doing one “FOLLOW-UP” async action in response to a trigger action, which if ur lucky happens at a URL split point™.
RFR gives you a natural contextual way to encode “follow-up” actions. More on that, coming soon.
WHICH BRINGS US to THE END
…Hope you liked the photos. Hope you have fun in the sandbox. Today’s adventure is really up to you. I can only lead you to water. Very tasty water that tastes like craft beer. Or, rather, Belgian beer — because that’s my favorite.
Enjoy Fellas! And ladies, cuz I know you’re out there. Stay coding, as we build the future according to our vision. And thanks so much Ives van Hoorne and Bas Buursma for making the super sexy and luscious Code Sandbox. I think what they’ve made will evolve very far and will likely turn out critical for many of us on our coding journey. Wish you guys the best of luck!
1 Love: [js]. The React Stack.
While you ponder what has begun to seep into your subconscious (and hopefully play with Ive’s amazing Code Sandbox), let this instrumental play out for you:
And so you don’t gotta scroll to the top:
Understanding the architectural decisions behind the tools you are using is perhaps more important than the many things…medium.com
The purpose of this article is to debunk the effectiveness of route-matching components + nested routes when using…medium.com
The code has been cracked for a long time now for server-side rendering and code-splitting individually. Until now …medium.com
A month ago Webpack’s creator, Tobias Koppers, unleashed “The big plan” for CSS in Webpack in his article “The new CSS…medium.com
Webpack 2.4.0, which came out a few weeks ago, launched with a very interesting new feature: “magic comments.” In…medium.com
You still here??
Tweets and other love are much appreciated. Find me on twitter @faceyspacey Want to stay current in Reactlandia? Tap/click “FOLLOW” next to the FaceySpacey publication to receive weekly Medium “Letters” via email 👇🏽