faceyspacey / redux-first-router

🎖 seamless redux-first routing -- just dispatch actions
MIT License
1.56k stars 143 forks source link

Route precedence #50

Closed tiagoskaneta closed 7 years ago

tiagoskaneta commented 7 years ago

As routesMap is an object and the order of route matching depends solely on Object.keys return value. If I do something like:

const routesMap = { 
  HOME: '/home',
  USER_NEW: '/user/new',
  USER: '/user/:id',
}

There's absolutely no guarantee that the USER_NEW route has the precedence over the USER route.

It's possible to use regex in the matching:

const routeMaps = {
  HOME: '/home',
  USER_NEW: '/user/new',
  USER: /user/(((?!new).)*)$/
}

But that would cause the payload to be number indexed instead of named: {0: "123" }

Is this by design? This use case would definitely be benefited by some ordering mechanism in the routes. Either an order parameter or routesMap accepting an array instead of an object would be fine I believe.

Do you see this as a valid use case?

faceyspacey commented 7 years ago

there's no guarantee but it does respect the order of keys pretty much everywhere. Do u have any links on what the official best practice is here. I thought it basically was that we could rely on the order of keys, or maybe just for small objects.

faceyspacey commented 7 years ago

Yes order is important. Ur supposed to be the more important route first.

As for the regex, that's inherited from reg-exp. you can actually do some interesting things I haven't documented.

faceyspacey commented 7 years ago

Basically matches via parentheses or just * are indexed by number. Perhaps it should just go in an array called matches at payload.matches. PRs welcome

faceyspacey commented 7 years ago

Essentially it's "undefined" behavior right now. I never needed it but there are extremely valid tho rarer uses cases for it.

faceyspacey commented 7 years ago

To paint the fullest picture, here's the extreme: dynamic types that take the match, capitalize it and insert it somewhere in the type like this 'MY_$1_TYPE' ...we won't do that tho as there other ways to accomplish the same thing with less complexity

faceyspacey commented 7 years ago

We just want the array of matches so u can decide what to do.

A nice use case is just using * at the end and capturing all remaining path segments. It allows u to dispatch a type for a variety of URLs. Say, any URL in a github directory. There's no way to create a good action type for every URL u might visit. So we just send the match as the payload and then u can use it to show different files in a repo like GitHub does.

tiagoskaneta commented 7 years ago

FYI: http://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-enumerate

Specifically:

The mechanics and order of enumerating the properties is not specified

I believe it's usually reasonable to expect the values to be returned in the order of initialization, but I don't believe the logic should rely on the certainty that that'll be the case.

faceyspacey commented 7 years ago

I would agree except I think it is 100% reliable in the major browsers.

Need more proof to the contrary. If not, we add an order key.

faceyspacey commented 7 years ago

I only did it cuz I saw lots of other packages do it. We could all be wrong tho.

tiagoskaneta commented 7 years ago
const obj = {
    "a": "value a",
    "b": "value b",
    "1": "value 1",
    "2": "value 2"
};
Object.keys(obj)

In Chrome, will output (4) ["1", "2", "a", "b"]

faceyspacey commented 7 years ago

that's interesting, but it respects the order of keys based on letters and doesnt alphabetize them.

const obj5 = { 
  "99": "99", 
  "2": "value 2", 
  "b": "value b",
  "a": "value a",
  "1": "value 1"
};
Object.keys(obj5)

...numbers it always orders. but we aren't dealing with numbers for keys.

faceyspacey commented 7 years ago

I'm gonna close this cuz in Firefox and Chrome order is respected for keys that are strings, which they always will be with this package. If someone comes back and says IE or Safari or something doesn't respect them, we can address it then.

GuillaumeCisco commented 7 years ago

Sorry to comment this closed issue, but I think something important was pointed out by this discussion. If the implementation of injected routes is made, I think the order will be very very important. But maybe I'm wrong.

The package normalizr transform objects in two nested objects : one entities with an object of {id: object} objects, another with a results list with the id in order. Maybe it will be usable. Just an idea.

Thoughts ?

faceyspacey commented 7 years ago

good point. ..though if the order is only dependent within the given injection (which is likely the case 90% of the time), then we're right where we were before.

I probably will do the order feature at a certain point. Other things will also make it important, like URLs that are more dynamic than :param which use regexes.