Skip to content
This repository was archived by the owner on Oct 26, 2018. It is now read-only.
This repository was archived by the owner on Oct 26, 2018. It is now read-only.

Support query params? #95

Closed
Closed
@kimjoar

Description

@kimjoar

This morning I've been playing around with how we could support query params in redux-simple-router (just as a thought experiment).

In history.listen we receive a Location. With pushPath and replacePath we can change the API to accept LocationDescriptors. However, with no way of creating a LocationDescriptor object from a LocationDescriptor string, it's difficult to support query params.

Here's an example of the problem:

pushPath('/foo?a=b')
// store:
{ location: '/foo?a=b' }


pushPath({ pathname: '/foo', query: { a: 'b' } })
// store:
{ location: { pathname: '/foo', query: { a: 'b' } } }


history.push('/foo?a=b')
// store:
{ location: { pathname: '/foo', query: { a: 'b' } } }


<Link to='/foo?a=b'>
// store:
{ location: { pathname: '/foo', query: { a: 'b' } } }

The problem is of course that every time you pushPath you will get the exact LocationDescriptor you pass in into the store, but every time you history.push or <Link> you'll get an object. We then can't reliably support query params. (If you're very strict about always passing in a LocationDescriptorObject you would have query support, but that feels very fragile.)

We can of course use history.createLocation right now, but it's most likely no longer going to be public in history V2.

To support query params we need to be able to create a LocationDescriptor object both from a LocationDescriptor string and from a Location. We could then easily support query params, and we could also deepEqual check them without knowing about query or anything else that's actually part of the LocationDescriptor (which is how we stop cycles, #50). With a createLocationDescriptor (that always returns a LocationDescriptorObject) our code base would actually be simpler, and we would get query support for free.

Okey, so some potential solutions:

Keep the solution we have now

I.e. path and state in store, but change to accepting LocationDescriptor in push and replace. We don't support query params.

Verbatim LocationDescriptor in store

We have to make it very clear that this is either an object or a string. So it's most likely not very usable for people. We "support" query params, iff you're very strict about always passing in a LocationDescriptorObject. Fragile.

Always go through history "before" store

pushPath
-> UPDATE_PATH_INTERNAL action
-> store.subscribe callback
-> history.push
-> history.listen callback
-> UPDATE_PATH action
-> store.subscribe callback where we break cycle

I.e. we don't trigger UPDATE_PATH immediately, but only within the history.listen callback. We would then reliably have a LocationDescriptorObject in the store, and we could therefore reliably support query params.

This is of course a more complex solution.

Conclusion

It was interesting going through the different solutions, but with createLocation going away and no createLocationDescriptor on the horizon I think it's best to just keep our current solution. I don't think it's worth the added complexity.

Maybe someone else has ideas on how to solve this? Or maybe this is another case for keeping history.createLocation public? @jlongster @mjackson @taion @justingreenberg

(Hopefully I haven't overlooked something very obvious 🙈)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions