Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

redux-tiny-router #656

Closed
Agamennon opened this issue Aug 30, 2015 · 16 comments
Closed

redux-tiny-router #656

Agamennon opened this issue Aug 30, 2015 · 16 comments

Comments

@Agamennon
Copy link

I just wrote a tiny router for redux called redux-tiny-router it is basically 3 parts, all quite small, one middleware one reducer and some action creators, i was inspired by the cerebral reactive router, to treat the router as just state, there is no wrapper functions no components, just add in the middleware the reducer, and make use of the actions provided to tell the router what to do.

I would like some feedback as to if this is a good approach! i like the result a lot for the moment.

Also it has some nice functionality on the server side for universal apps, it tracks your promises to know if the app is ready to render, and even re-render server side if there is side effects on the first render (component will mount)

Please know, the documentation is just a first draft and the server side part is implemented but not documented.

Again any feedback is appreciated!

@dbrans
Copy link
Contributor

dbrans commented Aug 30, 2015

@Agamennon: That looks pretty cool.

@alkhe
Copy link

alkhe commented Aug 30, 2015

@Agamennon I don't like the rtr prefix in your API, but I really like your implementation. Good start.

@Agamennon
Copy link
Author

Glad you guys like it, also, anything can change, the prefixing is there to avoid collision in case of user bindActionCreators, it's trying to be a good citizen, maybe unnecessary?

@mindjuice
Copy link
Contributor

I've been wanting something simple like this to use with redux.

A few questions:

  1. Does the route state go both ways? In other words, if I type a URL with query parameters, then they are automatically reflected into the state.
  2. Related to How to dispatch many actions in one action creator #1, does the router state get updated as you use back/forward buttons?
  3. Since you want access to the store (you need to call init(store)), should this maybe be a store enhancer instead of just middleware?

@Agamennon
Copy link
Author

@mindjuice , yes if you type, or use the back and forward buttons the state will be updated, more accurately an action will be fired that will become state.
init(store) is just the place where you give your store to redux-tiny-router to be able to fire dispatch and getState, on event listeners like window.onpopstate and window.onbeforeunload.
Now on the matter of a store enhancer, sure it could be one, but i think one of the nice things about redux-tiny-router is that it is not "trying that hard" nor modifying anything, its using the same api and flow of a regular app to provide said app with a router. It makes it less "magic" to reason about when understanding how it works. but in the other hand a store enhancer is not hard to create and could simplify usage a little, if there is a need to go that direction i see no problem implementing it.

@mindjuice
Copy link
Contributor

All of the state in my app lives in the state tree already, but I would like to persist some of that in the route as well (e.g., a date range to display data for in the app).

I am hoping to avoid having both state.router.query.dateRange and state.view.dateRange, and would rather have the app keep the state where it makes sense for it (e.g., state.view.dateRange) and make the router pickup bits of state I want to persist and put them in the URL query parameters.

Something along the lines of:

// First param is the query item name, second param is a path into the state tree (several options for this)
router.addQuery('dateRange', 'state.view.dateRange');

After that, the router would maintain the relationships when things change in either the URL bar or the state.

I'm actually doing this now with some ad hoc code and it's working fine, but it would be nice to genericize it.

@mindjuice
Copy link
Contributor

There's probably a better way to do this, but I haven't had time to work on it much yet.

@Agamennon
Copy link
Author

@mindjuice will push a new version today or tomorrow, it will have some changes and a boilerplate, perhaps it will clear things up a bit

@Agamennon
Copy link
Author

@mindjuice new version is up, with an example app, take a look, i hope it explains it batter

@gaearon
Copy link
Contributor

gaearon commented Sep 4, 2015

I'm closing, as feedback has been received, and there is nothing actionable for us here.

@gaearon gaearon closed this as completed Sep 4, 2015
@Agamennon
Copy link
Author

@gaearon , this new version added a bunch of things, talking about feedback, i would love to know your opinion!

@gaearon
Copy link
Contributor

gaearon commented Sep 5, 2015

You asked for it, so please forgive me if I am being harsh. :-)
I mean well.

As I wrote above I don't like the enhancer because it wants to “own” Redux APIs. Providing your own applyMiddleware and shortcuts like “just pass an object of reducers” is going to make it harder for everyone in the ecosystem, because these things have no relation to routing.

Also, I think we need to focus community effort instead of spreading it. There is already rackt/history that a lot of thought went into (basically whole year of @mjackson's and @taurose's experience with dealing with browsers, routing, and their edge cases). There is already rackt/react-router which is still work in progress, but I know @ryanflorence keeps an eye on supporting scenarios like authorization, animations, async transitions, async-transitions-with-showing-previous-data-and-a-loading-spinner, code splitting for route definitions and gradual path matching, nested route matching, nested-route-matching-for-named-children-like-sidebar, modals, etc. I think it is much more beneficial to contribute to making React Router work better with Redux, than to write another router only to bump into the same problems and design decisions.

@Agamennon
Copy link
Author

@gaearon The enhancer is optional, there is always the option to bring it all by hand, as stated in the documentation. I have no problem with harsh criticism, but by reading this i have the feeling that you don't like tiny-router because there are other routers out there. This is quite an argument coming from someone that invented a "flux implementation" in a sea of flux implementations, and guess what? Thank you! yours is cooler and sleeker, an easy choice for me, and with redux-tiny-router, i am not trying to compete with @mjackson @ryanflorence , if you look on how i am approaching this is completely different! i would argue that for a class of problems it's an elegant solution, its removing responsibilities from within the router, not adding them. I hope i didn't come out confrontational in this response, i just want you to look on how this router is solving some of those complicated problems, some of them are just not complicated anymore.

@gaearon
Copy link
Contributor

gaearon commented Sep 5, 2015

by reading this i have the feeling that you don't like tiny-router because there are other routers out there

Sorry, but that was not point. A router is a different beast than a Flux library. It has to interoperate with the browser, work consistently with many edge cases and browser bugs, and provide functionality useful for non-trivial apps at the same time. You don't want to write your app, and then someday discover that the router you chose makes code splitting difficult, for example.

In other words, there are many features you seem to consider unnecessary in a router, but I can't imagine using one in a real app if it doesn't have these features. As the most basic example, redux-tiny-router does not seem to restore scroll position. This is a very important feature of a client-side router if you want to create quality apps, and if it is absent, I can't use the router. Now, if you try to implement it, you'll soon see the same problems with browser edge cases as Michael and Alexander found, and when you figure out how to work around them, you'll basically get rackt/history.

Now, in a real app, you'll want nested view matching. (Come on, by now every major router does this because it's so essential for client side apps.) You can say “my router is tiny; it's not concerned with matching”, but then you're just pushing every consumer to implement the same thing, which isn't very helpful because the implementation will likely end up similar to rackt/react-router (which uses rackt/history as the engine under the hood).

I hope this makes sense.. I'm not bashing your attempt at reinventing the router. We just have different definitions of “router”. You call “router” something that matches paths, I call “router” something that handles all edge cases for me, supports multiple history implementations, handles scroll position restoration, async transition hooks, etc, and is ready to plug into my existing app to take care of all routing concerns.

@Agamennon
Copy link
Author

Well first let me fix my previous statement, you are right, comparing flux with a router is not a good comparison, my point was, that same way you felt flux should be done differently i felt for react-router, for some use cases.

But let me clarify, if one where to build a traditional router using react components, it would be darn near impossible to do something superior to what react-router has achieved, also react-router takes care of many uses cases, maybe all of them!

Then why did i felt this way about it? well it's kind of your fault! when i saw redux, and the way it handles state, plus the way react works, i thought, why do i need this "overseer" this "controller" that will decide what will render in my applications, why can't i just keep closer to what react preached, state -> app.

Before i get misunderstood, my mind there was not thinking about a general solution, but one that fitted my use-case and possibly many others, for one, code splitting by design, will NEVER happen on rtr, it would need to morph into something different, as the router does not have any information about the app. If your app needs the router's help to do code splitting, use react-router or another splitting technique. Some apps do not need code splitting on route level, they can do just fine with resource splitting.

Nested view matching, this concepts kind of emerges naturally in the way you build your react app with rtr, since router -> state -> app , you can have as complicated and convoluted UI you want!, rtr have tools to help there, route definitions and utils.check, will give you a lot of leeway in the way you structure the final application, so stating that "my router is tiny; it's not concerned with matching" is not quite accurate, it gives you the state and tools to help you. Granted you do that in a different way, it's more of a nested state matching.

Support for multiple history implementations?, it doesn't have one, and no plans for the moment to implement, rtr is for evergreen only, as far as my limited testing goes, it works on IE10+ Chrome, Firefox and Safari. if that changes one day i could bring rackt/history in, and not re-invent the wheel.

Scroll position restoration, funny you bring this up, i was fiddling with this, and the redux state is helping alot

Finally, redux-tiny-router is not trying to be react-router, it's a router (or whatever you want to call it) to be used with redux, and for certain cases, i think for those cases it's great! and others too, for the short time it was "featured" as an open issue i got a lot of positive feedback.

The integration with redux is awesome, you can use middleware to do route auth if you want, handles async on universal apps, and all sorts of new things i am just finding out!

Perhaps if it had more exposition, the extra hand could help a lot in shaping rtr to become a cool tool if you are using redux and it fits your requirements.

Finally i must say i am a little disappointed, i was not expecting you to love it, or even use it, but i can't help but feel that you have dismissed it a little too quickly.

@gaearon
Copy link
Contributor

gaearon commented Sep 6, 2015

But let me clarify, if one where to build a traditional router using react components, it would be darn near impossible to do something superior to what react-router has achieved, also react-router takes care of many uses cases, maybe all of them!

This is not true. React Router has some problems. In fact improving React Router to better fit Redux is what @acdlite has been working on, and some of those ideas were used in 1.0.0-beta4 which is very important to us.

Then why did i felt this way about it? well it's kind of your fault! when i saw redux, and the way it handles state, plus the way react works, i thought, why do i need this "overseer" this "controller" that will decide what will render in my applications, why can't i just keep closer to what react preached, state -> app.

React Router is not set in stone. That's the issue—I think work should be done to help it better embrace Redux's paradigm. That's exactly what Ryan's and Michael's plan was.

Finally i must say i am a little disappointed, i was not expecting you to love it, or even use it, but i can't help but feel that you have dismissed it a little too quickly.

I'm not “dismissing” it—you asked for feedback, I'm telling you that there are many reasons why I wouldn't use it personally. I'm happy if other people are using it; all I'm saying is it doesn't satisfy my use cases. The effort we already put in React Router and the fact that it can be made better instead of disregarded as “old way of doing things” is a big reason for me too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants