A Simple Way to Route with Redux
jlongster.com
jlongster.com
This is how most server side MVC frameworks work too, it makes server-side rendering super simple (even with shared app state between users), it fits with RESTful designs, it forces you to design state into URLs so users can share links by definition, and so on. It just seems obvious to me.
But somehow, Flux and most things derived from it seem to disagree and insist on storing the "this is what the user looks at right now" information in the application state. To me, that hopelessly convolutes things. But I've been wrong before and I'd like to learn.
Can anyone explain to me why that's better? I might just be a conservative, grumpy old man here.
I've actually been struggling with some of these. For example, whether a dropdown is expanded or not is state, but it just doesn't feel 'big' enough to even be in the reflux store. Plus it turns out to be a major hassle to implement such a dropdown, with actions firing the new state all the way up to the store and the state then being passed down the whole chain of components.
Following redux orthodoxy here also precludes you from using existing libraries (bootstrap/jquery) and kinda leads to reinventing the wheel. I had no idea how much consideration a simple dropdown takes until I looked at the bootstrap/jquery source for it.
https://github.com/guscost/kendo-react-wrappers
Perhaps not acceptable for performance-critical or first-class consumer-facing UIs, but you get nice cross-browser compatibility and pre-built widgets that can be surprisingly complex.
Internally the Kendo library is going to maintain its own state and manipulate the DOM elements needed for each widget, and I only know a bit about how that works. Most of these wrappers only run render() once because React would throw all kinds of errors if it tried to diff the DOM inside the components.
Updates are handled in componentWillReceiveProps, and whenever the component can be updated with the new props without destroying and recreating itself, the updates happen via the Kendo API (after the wrapper checks if the new value is different). This means that for common use cases these wrappers should perform just about as well as the widgets do normally. Also every controllable setting is exposed as a prop, and the props are synchronized on every update. Props that are not passed in are reset to the defaults, meaning these widgets should appear stateless to the containing component.
The react-kendo project[0] uses some very cool introspection to provide full support for all the Kendo widgets, and it looks like it should be reliable and stateless. However it destroys and rebuilds the widget on every update. While that probably isn't going to be a huge performance hit it certainly makes a difference.
"current thread" doesn't need to be stored in the state in an explicit way. rather, you just need to be able to derive the "current thread" (or whatever) from the state.
so, your state contains the current route, and you use that to derive the "current thread" and then if redux has any state corresponding to that thread (or whatever) you can get that, too.
So the SPA's state is different than just "we're now pointing to this resource" -- much more full and complex.
This is the second article I've been interested in today here on HN that seems, to me at least, to go on and on extolling the virtues of said framework/extension/etc, and in the end gives absolutely no hint of how to use it.
Yes yes I know...farts like me are behind the curve/too slow/fat/old/stupid etc to understand all this modernity, but really, is it too much to ask for a small example of the Greatness?
...in this case, it's not a widget, but a routing library. Actually a slightly nicer wrapping library around the same base routing library used by basically every React project, which means that for the user, it'll look exactly like every project that doesn't use it too. The only thing to "see" is basically the API docs.
(That being said, maybe that could be made clearer in the blog post...?)
I've been delaying learning React for awhile. After a period of ranting about "another JS library, another JS tool etc etc!!", I got tired of my ranting and have been giving a decent go at picking up React and a myriad of related tools (webpack, flux, react-router...).
It turns out, if you have some experience of framework, whether it be AngularJS or Backbone (I come from BackboneJS and Marionette background), it doesn't take you too long to learn these things.
I signed up for Egghead, searched around for awhile for the latest relevant tutorials, opened up many Chrome tabs and jumped around different places, but after a week, things are falling into places (JOY!).
Learning part is frustrating, because there are references to old versions, old tutorials and you have to somehow mine through to make sense for yourself. But what isn't thesedays?
I haven't picked up redux properly yet, but now I get Flux, I don't think it'll take too long before applying it. Redux Router? Bring it on!!
It really is simple, as stated in his title, and I would definitely recommend it if anyone is using Redux and React Router.
If you already have a lot of behavior defined it might take a little while to convert it all to reducers (action + currentState -> newState functions) but it's a pretty simple refactor.
(EDIT: ok, the last statement was a simplification. But generally you don't need to, but you could manually move data into the state if you needed to)
https://github.com/teambition/router-view
And it's demonstrated at here:
It's also worth mentioning that this lib also provides a really useful action creator- updatePath(). It allows you to navigate from other action creators, for example, in response to a successful AJAX call. You could achieve that a couple other ways as well, but this is the simplest/cleanest way I've seen so far.
redux-router is still in beta, so this isn't entirely fair.
With React libraries in particular, the ecosystem is still evolving so fast it seems relevant to note which are bug-prone, popular, etc, just to try and predict which will still be alive in a year.
React is just way too heavy for my needs and if I'm going to put markup in my JS files I might as well just use Hyperscript so it actually is javascript. By pairing virtual-dom with redux, my entire application's state, including how the UI currently looks, is held in one large immutable object which I just apply reducers to when I want to change the interface. React, and all the other modern front-end frameworks, still have to deal with state living in two places (in stores and in the DOM) whereas in my apps' state only lives in once place - the Redux store.
Don't get me wrong, React pushed front-end development forward in a big way, but a lot of cool stuff has come out of the woodwork in response to it that is definitely worth checking out. I'm more interested true functional-reactive web libraries than React. Cycle, Elm, Ohm, and Mercury are a few I would recommend checking out.
> After integrating redux and react-router in my site, I extracted my solution to a new project: redux-simple-router. The goal is simple: let react-router do all the work. They have already developed very elegant APIs for implementing routing components, and you should just use them.
The explicit goal of the project is to take advantage of react-router's existing tools when used with redux, it doesn't make any sense to lament that it depends on react-router.
What is the benefit of using react-router (I am assuming on the client side) versus using a server side router that comes with whatever web framework that you are using?
In a single page app, your client routes (representing individual views) don't have to map directly to your server side routes, which gives you the ability to have pages/views that don't require a server roundtrip.
You can also cache frequently used data on the client and use them on multiple "pages" as you navigate through your client side routes/pages, loading "page" specific data from your API as needed.
So in general it gives you more tools/options for building a snappier app.
As I understand it, client-side routers manage the relationship between URLs and state. The parts of state that are relevant when a page/view might be bookmarked/shared etc. are encoded in the URL, and a given URL can be decoded into an initial state.
I'm now wondering if the first direction (state->url) couldn't just be thought of as a component. It just extracts parts of state and renders it into a string. The other direction would then be an action.
The specific component/state rendered is a reaction to the URL, not the other way around (this can get cloudy with semantics though). Keeping the URL and the current page state in sync takes the form of updating the path, and having your application react to that.
You're right it is perfectly feasible to render a different page/view when a link is clicked without a client-side router library, but the "swapping out components" part can get tricky for non-trivial cases like a hierarchical UI, or components that need to consume URL params.
A client-side router like react-router abstracts away a lot of the hard stuff you'd quickly run into on your own if A.) your app has navigation, and B.) you want to have URLs associated to views/states.