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

Modal base on route #1172

Closed
swolfod opened this issue May 9, 2015 · 17 comments
Closed

Modal base on route #1172

swolfod opened this issue May 9, 2015 · 17 comments

Comments

@swolfod
Copy link

swolfod commented May 9, 2015

So basically what I am trying to achieve is the Pinterest style modal page for their pins. Whichever page you are on, when you click on a pin a modal with the pin details pops up, and the page where you are from still sit in the background. The url in the address bar changes so you can link to the pin from other sites or share it to your friends. And when you close the pin modal you go back to previous page.

Is react-router supporting this kind of routing?

@genxstylez
Copy link

I want to know too! Can anyone help?

Thanks!

@BowlingX
Copy link

Just do everything normal and create the modal (with $replaceThisWithYourFavoriteModalLibrary) in componentDidMount and/or open it in componentWillReceiveProps later. You may also just apply a class to your "detail" component that will set position:fixed to the detail container and apply propper formatting however your modal should look like.

Rough Example:

componentDidMount() {
      const modalContainer = this.refs.modalContainer.getDOMNode();
      YourLibrary.createModal(modalContainer);
 }
render() {
   return <div className='modal' ref='modalContainer'/>
}

@swolfod
Copy link
Author

swolfod commented May 29, 2015

The problem is, when you get to the render() function through url routing, the 'previous page' is already gone, no way to pull it back and make it 'sit on the background'.

Anyway, after a couple days effort I believe this kind of routing is not in favour of the library's philosophy, where (I think) it is believed that url should mean a solid state of the app, so whenever a user hits a url, exact same content should be shown.

So if you believe otherwise, you might need to look somewhere else for solution.

@ryanflorence
Copy link
Member

I've been wanting to support this for a while and we do now in 1.0!

Check out the pinterest example on master.

@genxstylez
Copy link

Nice

@andreigabreanu
Copy link

I still see it as incomplete. Although its nearly perfect, it seems that on refresh, even if you arrive on the same URL with the modal, the modal will not trigger. Which kind of makes sense based on the architecture. But maybe you guys have an idea?

Example:
example.com/modal => shows modal

  1. Click a Link to=example.com/modal => shows modal
  2. Refresh => no modal, content is rendered in page instead.

@switchtrue
Copy link

Probably worth noting here that when looking at the source for the pinterest example be sure to check the code for the exact version of react-router you are using.

The example in master currently passes through the Link state as follows:

<Link
  key={picture.id}
  to={{
    pathname: `/pictures/${picture.id}`,
    state: { modal: true, returnTo: this.props.location.pathname }
  }}
  >

Is 1.0.3 to must be a string and thus passing through state should be achieved like this:

<Link
  key={picture.id}
  to={`/pictures/${picture.id}`}
  state={{ modal: true, returnTo: this.props.location.pathname }}
  >

@crisu83
Copy link

crisu83 commented Dec 31, 2015

+1 on @andreigabreanu comment

@timdorr
Copy link
Member

timdorr commented Dec 31, 2015

What kind of modals libraries is everyone dealing with? I'm finding the react-overlays library from the react-bootstrap folks works when I navigate to a route: https://github.com/react-bootstrap/react-overlays

@crisu83
Copy link

crisu83 commented Dec 31, 2015

I'm using react-modal and so far it has done the job well.
On Thu, 31 Dec 2015 at 16:35 Tim Dorr [email protected] wrote:

What kind of modals libraries is everyone dealing with? I'm finding the
react-overlays library from the react-bootstrap folks works when I navigate
to a route: https://github.com/react-bootstrap/react-overlays


Reply to this email directly or view it on GitHub
#1172 (comment)
.

@reintroducing
Copy link

Don't mean to resurrect an old issue but I think this got closed a bit prematurely. I'm trying to implement this now based on the Pinterest example outlined by @ryanflorence and I'm running up against the same issue that @andreigabreanu describes. On refresh, this completely breaks down and the modal content is rendered into the page instead.

Has there been any headway on this at all in the current version of react-router?

For what it's worth, I'm using my own Modal component but it works in much the same way other React modal components work, really.

@mbrevda
Copy link

mbrevda commented Sep 1, 2016

The Pinterest example seems to have two flaws: 1. there is no "back" support (i.e. previousChildren isn't preserved when navigating from a modal to another modal) and 2. like @reintroducing said, when navigating initially to the modal route, there is no background. Is there a simple way to implement it that I'm missing?

@taion
Copy link
Contributor

taion commented Sep 1, 2016

There is no modal route. That's the point – it's one route that depends on how you get there. Note that on Pinterest itself, refreshing when you've popped up the modal for a pin will also drop the modal, just as in the bundled example.

@mbrevda
Copy link

mbrevda commented Sep 1, 2016

refreshing when you've popped up the modal ... will also drop the modal

That's exactly the issue were talking about. While some things are just fine showing in their own page, that's not always desireable.

(For example, some sites link directly to example.com/login when advertising their site. It's a bit silly though to bring a user to a site and show them only the login page. Hence, it's desirable to have the sites default route (or whatever) rendered underneath.)

It would be great if there were a simple way to say "render this route WITHOUT removing the last route", and a way to specify a default route if there is no previous route.

@sf-old
Copy link

sf-old commented Sep 1, 2016

@mbrevda could you just handle that yourself in your root route component? If you want to render both the current route and the previous route, store the root component's children (the child route) prop in your state and do your own logic to determine whether to render the children from props/state/both.

Perhaps not the best solution but we do something similar w/ our use of react-router on www.treesnetwork.com and it solves our problem.

@mbrevda
Copy link

mbrevda commented Sep 1, 2016

could you just handle that yourself in your root route component?

Pretty sure I could. I was hoping, based on my needs and the many other requests here, that there could be an official solution.

@OliverJAsh
Copy link

OliverJAsh commented Aug 15, 2017

For anyone who stumbles across this issue trying to achieve parity with Twitter/Pinterest modals, here are a few things to note. The examples (v2 and v4) don't cover everything needed to achieve parity:

  • History state used to enable/disable the modal—like in the examples—will be persisted across page reloads. Twitter/Pinterest do not behave like this—they switch to the permalink view on reload. This can be worked around by calling router.replace to clear the state before the main app component enters (e.g. onEnter).
  • On Twitter/Pinterest, exiting the modal will navigate the browser back to the route shown prior to the modal entering (rollback)—for example, if I close the modal, I can go forward in my history to see the modal again.
    I achieved this by keeping a count of location changes: Add location.index history#334 (comment). I dived into the Twitter source code to work out how they were doing this. This is what I saw:
    this.rollback = function(t, e) {
        e.rollbackCount > 0 ? (this.isRollback = !0,
        history.go(-e.rollbackCount)) : delete this.isRollback
    }
    They set rollbackCount as location state when calling history.pushState. The same could be achieved by providing state to the Link component.

@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

No branches or pull requests