Skip to content

Multiple RouteHandler components #564

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

Closed
tmcwilliam opened this issue Dec 5, 2014 · 7 comments
Closed

Multiple RouteHandler components #564

tmcwilliam opened this issue Dec 5, 2014 · 7 comments

Comments

@tmcwilliam
Copy link

Is it possible to render a sibling element based on a nested route?

For example:
/stories - would show a list of stories
/stories/1 - would show a list of stories, plus a modal with details for "story_id: 1"

Below is my basic setup. You'll notice that I need modal div to be a sibling of main. The modal div's RouteHandler would need to map to my Detail handler.
App.js

<div className="container">
  <div className="main">
    <RouteHandler />
  </div>
  <div className="modal">
    <RouteHandler />
  </div>
</div>

route.js

<Route handler={App} path="/">
  <Route name="stories" path="/stories" handler={Stories}>
    <Route name="detail" path=":id" handler={Detail} />
  </Route>
</Route>

This could be a similar issue to #551 or #427, but #551 is still open and #427's solution is to check the params which forces all routes with an id to use a modal.

@tmcwilliam
Copy link
Author

I do realize that this goes against the "nesting" approach, however it appears that you might be heading into this direction. If not, maybe you could suggest a better approach than parsing params.

@jsdir
Copy link

jsdir commented Dec 21, 2014

👍

@jsdir
Copy link

jsdir commented Jan 1, 2015

What if RouteHandler could choose whether or not to render the handler based on dynamic conditionals?

@ryanflorence
Copy link
Member

I'm guessing you're trying to get around some CSS constraints by not wanting to render a modal in a nested way, and that's why you want to render the modal content in App instead of just doing the happy path thing and rendering it in Details. Your UI is still nested, App -> Stories -> Details even if Details is in a modal.

To deal with this, you pass a function prop down to receive modal content:

var App = React.createClass({
  getInitialState () {
    return { modalContent: null };
  },

  handleModalContent (modalContent) {
    this.setState({ modalContent });
  },

  render () {
    var modalContent = this.state.modalContent;
    return (
      <div>
        <RouteHandler showModalContent={this.handleModalContent} />
        {modalContent ? <Modal>{modalContent}</Modal> : null}
      </div>
    );
  }
});

var Detail = React.createClass({
  componentDidMount () {
    this.props.showModalContent(
      <div>
        Details
      </div>
    );
  },

  render () {
    return null;
  }
});

I wouldn't do that though. I would render a modal in Details, you can even use our modal lib :) https://github.com/rackt/react-modal

So Detail would be essentially this simple.

var Detail = React.createClass({
  render () {
    return <Modal isOpen={true}>Detail</Modal>;
  }
});

You won't run into any CSS constraints either because even though React Modal is declared inside of nested JSX markup, it actually renders the modal into document.body using a "portal".

@tmcwilliam
Copy link
Author

These are nice ways to get around the issue, but I was hoping there would be a way for react-router to leverage the burden of displaying the Modal by using a handler.

I still have to parse the url (although react-router gives me nice util methods to do so) to determine when to show the Modal rather than having react-router steer me into a handler.

@ryanflorence
Copy link
Member

This is really about getting data from a component down the tree up to the top to toggle the display and content of a modal, which is the great problem everybody tries to solve in react :P Sorry, I'm going to close this because I don't know what the router is supposed to do for you here. If you have any epiphanies on how it could help, please post some code that shows how it could work.

@bbtfr
Copy link

bbtfr commented May 28, 2015

I think maybe we could do it in this way:

App.js

<div className="container">
  <div className="main">
    <RouteHandler partial="Main" />
  </div>
  <div className="modal">
    <RouteHandler partial="Modal" />
  </div>
</div>
var RenderPartialsMixin = {
  render () {
    var name = 'render' + this.props.partial;
    return typeof this[name] === "function" ? this[name]() : null;
  }
};

var Detail = React.createClass({
  mixins: [RenderPartialsMixin],
  renderMain () {
    return <SomeMain />;
  },
  renderModal () {
    return <SomeModal />;
  }
});

Edit: I've noticed that this is an old issue, but @ryanflorence might be working on it now #1008.
Edit2: I've rewrite as a mixin, I'm a coffeescript user, so sorry if there is any syntax issue.

@lock lock bot locked as resolved and limited conversation to collaborators Jan 24, 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

4 participants