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

Attach current location and params to context.router #3442

Merged
merged 4 commits into from
May 9, 2016

Conversation

gaearon
Copy link
Contributor

@gaearon gaearon commented May 9, 2016

Not sure if this is a great way to do it but let’s start here. Partially fixes #3325—at least for my use cases.

I’m not sure how to put route there because it depends on how deep you are. So I just limited it to params and location.

@gaearon gaearon added this to the next-3.0.0 milestone May 9, 2016
const router = createRouterObject(history, transitionManager)
router.location = null
router.params = null
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a big fan of duplication but it doesn’t seem harmful yet. Can extract to a method later if necessary.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we were imagining just creating a new this.router in componentWillUpdate every time, rather than keeping around a persistent one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just tried this but this doesn’t work for the initial render.
setState called inside componentWillMount will not cause componentWillUpdate to run.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can do it in both then? I think part of the reason @ryanflorence wanted to defer this to 3.0 was so that we could implement it in this way, and get away from some of the requirements around keeping track of a stateful router object.

@taion
Copy link
Contributor

taion commented May 9, 2016

We'd handle router.route when we got to per-route context providers for relative links.

@@ -62,6 +62,8 @@ const Router = React.createClass({
if (error) {
this.handleError(error)
} else {
router.location = state.location
router.params = state.params
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would adding routes here make sense as well? I've been trying to add tracking to an app with redux & react-router, in some redux middleware I imagine seeing me use this like:

import { LOCATION_CHANGE } from 'react-router-redux';

export default function analytics({ getState }) {
  return (dispatch) => (action) => {
    switch (action.type) {
      case LOCATION_CHANGE:
        track({ name: 'visit', ...visitTrackOptions(action.payload) });
        break;
    }

    return dispatch(action);
  };
}

function visitTrackOptions({ location, routes }) {
  const routePaths = routes.map(route => route.path);
  const pattern = filter(routePaths).join('/').replace('//', '/');

  return {
    weblink_url_full: location.pathname, //=> `/posts/foo-bar`
    weblink_url_pattern: pattern, //=> `/posts/:slug`
  };
}

Is adding routes here something that can be considered? Reason why I ask is because we've been trying to add tracking to an app via redux & react-router

Copy link
Contributor Author

@gaearon gaearon May 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you clarify how this is related to this PR? It only puts some stuff onto this.context.router so it is not related to react-router-redux or its actions.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought this was somehow the leg work to get eg location in redux as well, if it isn't totally my bad 😁 and feel free to ignore. (context)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd make sense to add routes here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the point I’m trying to make is you don’t need a special integrating library for React Router and Redux to work together. There are a few problems that need to be worked out for them to work fine without any libraries in the middle:

Neither of these are about putting something in the store. Rather, they are about making props from React Router easy to inject into connect()ed components that can read them from ownProps and use them for state selection. I hope this helps!

@gaearon
Copy link
Contributor Author

gaearon commented May 9, 2016

Update the PR to recreate the router object. I do it in the listen callback rather than componentWillUpdate so that it works the first time as well.

@taion
Copy link
Contributor

taion commented May 9, 2016

I don't think we can do this in <Router> – we need the same logic for the router object created in match().

@gaearon
Copy link
Contributor Author

gaearon commented May 9, 2016

Added the code to do this. It’s possible there is a nicer way to refactor this and split responsibilities between transitionManager and router differently but this can be done after shipping.

@taion
Copy link
Contributor

taion commented May 9, 2016

Cool, thanks. I do think there's a nicer cleanup possible here but we can leave that for later.

@gaearon
Copy link
Contributor Author

gaearon commented May 9, 2016

Cleaned it up a tiny bit in fbcbd94 because we only need the router once there.


if (nextState) {
const router = {
...createRouterObject(history, transitionManager),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make nextState an arg to createRouterObject? And just do createRouterObject(history, transitionManager, nextState) here and createRouterObject(history, transitionManager, this.state) in <Router>?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haha, just made that change. 👍

@gaearon
Copy link
Contributor Author

gaearon commented May 9, 2016

@taion

I discovered a problem: changing the context object does not propagate well with the current ContextProvider / ContextSubscriber because this.context.stuff still points to the old one (React doesn’t update it). We need to either fix ContextUtils (more difficult for the general case) or keep updating the same router object (easy).

^^ one of the reasons extracting these hacks into something general is hard. We always know our own cases, but it’s hard to fix all possible edge cases.

@gaearon
Copy link
Contributor Author

gaearon commented May 9, 2016

I’ll merge for now to unblock myself as I have little time to finish this. Please feel free to rearrange stuff as you see fit after me.

@gaearon gaearon merged commit 1bafa32 into remix-run:next May 9, 2016
@gaearon gaearon deleted the pass-params branch May 9, 2016 19:00
@taion
Copy link
Contributor

taion commented May 9, 2016

Sure – I think we'll have to go back to modifying the same object in-place, then.

@gaearon
Copy link
Contributor Author

gaearon commented May 9, 2016

#3443

@lock lock bot locked as resolved and limited conversation to collaborators Jan 19, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants