FormidableLabs / redux-little-router

A tiny router for Redux that lets the URL do the talking.
MIT License
1.04k stars 114 forks source link

How to render an overlay on top of main content (2 fragments at once)? #296

Closed markplindsay closed 5 years ago

markplindsay commented 6 years ago

Inside a <Viewer> component, I'm trying to render a MAIN PAGE (route /) with a big list of profiles.

Clicking on each profile's "View Details" link should take you to a PROFILE PAGE for a specific profile (route /profile/:pk). The MAIN PAGE should not be rendered when the PROFILE PAGE route is active.

Clicking on a profile's "Contact" link should open a CONTACT overlay (route /contact/:pk) on top of the MAIN PAGE. The MAIN PAGE with the big list of profiles should remain in view underneath the overlay. To be clear, CONTACT and MAIN PAGE should both be rendered.

I suppose I am trying to combine the "dat-boi" and "component-per-page" <Fragment> examples. But I am not doing something right, because my CONTACT overlay is not rendering:

const Viewer = props => (
  <div className="viewer">
    <Fragment forRoute="/">
      <div>
        <Fragment forRoute="/profile/:pk">
          <div className="profile-page">
            <h1>PROFILE PAGE</h1>
            View profile details on separate page. The big list of profiles is
            not rendered.
          </div>
        </Fragment>
        <Fragment forRoute="/">
          <div>
            <div className="main">
              <div className="content">
                <h1>MAIN PAGE</h1>
                <p>This is the main page with a big list of profiles.</p>
                <p><Link href="/profile/1">View Details</Link></p>
                <p><Link href="/contact/1">Contact</Link></p>
              </div>
            </div>
            <Fragment forRoute="/contact/:pk">
              <div className="modal">
                <div className="modal-dialog">
                  <Link className="closer" href="/">Close</Link>
                  <div className="modal-content">
                    <h2>CONTACT</h2>
                    I hope I can make this a overlay on top of the big
                    list of profiles, which is still rendered in the background.
                  </div>
                </div>
              </div>
            </Fragment>
          </div>
        </Fragment>
      </div>
    </Fragment>
  </div>
)

Here is my routes object. I don't know if this is helping or harming what I am trying to achieve.

const routes = {
  '/some-other-page': true,
  '/profile/:pk': true,
  '/another-unrelated-page': true,
  // I figured that nesting here would make both routes render at the same time?
  '/': {
    '/contact/:pk': true,
  },
}

I've tried all kinds of <Fragment> combinations and arrangements in <Viewer>. However, I either end up a) rendering things entirely separately in the "component-per-page" way or b) always rendering MAIN PAGE, with CONTACT and PROFILE PAGE rendered above and below it at the same time in the DOM.

I'm using "redux-little-router": "^15.1.1".

Thanks in advance, and I am happy to submit a PR to the README with any hints I get here.

markplindsay commented 6 years ago

I was able to get the desired behavior with this <Viewer> component code:

const Viewer = props => (
  <div className="viewer">
    <Fragment forRoute="/profile/:pk">
      <div className="profile-page">
        <h1>PROFILE PAGE</h1>
        View profile details on separate page. The big list of profiles is
        not rendered.
      </div>
    </Fragment>
    <Fragment
      forRoute="/"
      withConditions={location => location.route !== '/profile/:pk'}
    >
      <div>
        <div className="main">
          <div className="content">
            <h1>MAIN PAGE</h1>
            <p>This is the main page with a big list of profiles.</p>
            <p><Link href="/profile/1">View Details</Link></p>
            <p><Link href="/contact/1">Contact</Link></p>
          </div>
        </div>
        <Fragment forRoute="/contact/:pk">
          <div className="modal">
            <div className="modal-dialog">
              <Link className="closer" href="/">Close</Link>
              <div className="modal-content">
                <h2>CONTACT</h2>
                I hope I can make this a modal overlay on top of the big
                list of profiles, which is still rendered in the background.
              </div>
            </div>
          </div>
        </Fragment>
      </div>
    </Fragment>
  </div>
)

My flattened routes object, since I don't think nesting routes has any bearing on what I'm doing:

const routes = {
  '/': true,
  '/another-unrelated-page': true,
  '/contact/:pk': true,
  '/some-other-page': true,
  '/profile/:pk': true,
}

This seems like an abuse of withConditions for what I'd consider to be a common use-case, though. I'm going to leave this issue open in case someone can point me to a cleaner solution.

parkerziegler commented 5 years ago

@markplindsay Thanks for the issue report. As of December 10, 2018, this project is no longer under active maintenance and we will no longer be moving forward with issue requests. Thank you for helping to make redux-little-router better!