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

[added] <Routes handlerProps = {…} > #374

Closed
wants to merge 1 commit into from

Conversation

appsforartists
Copy link

Anything you pass into handlerProps will be passed as props into all your handlers.

For instance:

<Routes
    handlerProps =  {
                      {
                        "favoriteFruit": "banana",
                        "favoriteDrink": "smoothie"
                      }
                    }
>
    <Route handler = { Trunk } >
        <Route handler = { Branch } >
            <Route handler = { Leaf } />
        </Route>
    </Route>
</Routes>

if Leaf was the active route; Trunk, Branch, and Leaf would all be
called with favoriteFruit and favoriteDrink as props, like so:

<Trunk
    favoriteFruit = "banana"
    favoriteDrink = "smoothie"
>
    <Branch
        favoriteFruit = "banana"
        favoriteDrink = "smoothie"
    >
        <Leaf
            favoriteFruit = "banana"
            favoriteDrink = "smoothie"
        />
    </Branch>
</Trunk>

If the test can be improved, please let me know!

Anything you pass into handlerProps will be passed as props into all
your handlers.

For instance:

  <Routes
      handlerProps =  {
                        {
                          "favoriteFruit": "banana",
                          "favoriteDrink": "smoothie"
                        }
                      }
  >
    <Route handler = { Trunk } >
      <Route handler = { Branch } >
        <Route handler = { Leaf } />
      </Route>
    </Route>
  </Routes>

if Leaf was the active route; Trunk, Branch, and Leaf would all be
called with favoriteFruit and favoriteDrink as props, like so:

  <Trunk
    favoriteFruit = "banana"
    favoriteDrink = "smoothie"
  >
    <Branch
      favoriteFruit = "banana"
      favoriteDrink = "smoothie"
    >
      <Leaf
        favoriteFruit = "banana"
        favoriteDrink = "smoothie"
      />
    </Branch>
  </Trunk>
@mjackson
Copy link
Member

mjackson commented Oct 9, 2014

@appsforartists Thanks for this PR! It looks great. I'm not sure we want to merge it just yet, because the whole props discussion is ongoing. There are a few issues that all deal with it, namely #261, #319, #262 (indirectly), and #314. I feel like when we have the right solution to this problem, we can close all of these at once.

@appsforartists
Copy link
Author

I definitely understand wanting to keep API creep to a minimum.

FWIW, I haven't seen any proposals in those threads that address the handlerProps use case. The beauty of handlerProps is that it gives you one place to inject an effectively global set of props into all your handlers, which addresses both my use case and #314. So far as I can tell, the other issues are all discussing props that are local to a specific <Route>.

I'd really like to avoid manually passing props to a specific route (at least for the use cases here and in #314). It makes it way easier to build an ecosystem around ReactRouter if there's a single point-of-contact that can marshall data into the handlers.

Do you see a way to handle both the global and local use cases with the same solution?

@appsforartists
Copy link
Author

If there is the need to support both global-and-local props, one implementation would be having a handlerProps property on both <Routes> and <Route>. Then, the API is the same for each case.

In Angular's ui-router, you can pass injectables (their version of props) from anywhere in the tree, and they cascade down. That is, if you put a handlerProps on a parent <Route>, its children <Route>s would get those props too. However, I'm having a hard time thinking of a demonstration for that model that would be idiomatic for React.

@mjackson
Copy link
Member

mjackson commented Oct 9, 2014

@appsforartists Thanks for explaining how ui-router does it. That's actually really interesting.

@appsforartists
Copy link
Author

Sure thing.

I once worked on an admin console that was built in Angular. The routes worked something like this:

  • /login/
  • /app_name/
  • /app_name/users/edit/
  • /app_name/other_things/edit/

users was a prop pass into app_name. Then, any other view in that tree (i.e. /users/edit/ or /other_things/edit/) could request users and have the global instance injected. Since /login/ was in a different URL branch, you could go to that page without being logged in. Then, after you'd log in, the first view you saw in the /app_name/ branch would populate users, authenticated as you.

@appsforartists
Copy link
Author

Because of the way Angular works, those were blocking calls. You could return a promise instead of a value, and the transition would be blocked until the promise resolved.

@ryanflorence ryanflorence added this to the props Props PROPS milestone Oct 11, 2014
mjackson added a commit that referenced this pull request Oct 13, 2014
This commit adds the ability for route handlers to load props
they need for a given route, optionally asynchronously. Props
loaded in this manner cascade from route handlers further up
the hierarchy to children, such that props loaded by children
take precedence.

getRouteProps should return a "hash" of props, the values of
which may either be immediate or deferred using promises. As
promises resolve, forceUpdate is used to re-render the <Routes>.
If no props are promises, the operation is fully synchronous
and route handlers will have all the props they need on the
initial render.

As implemented, this work should satisfy the use cases in #319,
 #261, #314, #374, and (indirectly) #262.
@appsforartists
Copy link
Author

I tried implementing something similar with getChildContext, but my context isn't being passed through (perhaps because of react#2112).

@rpflorence + @mjackson, it sounds like you're leaning towards closing this in favor of #396. This may sound crazy but considering the tiny footprint of this PR, would you be amenable to making #396 the recommended/documented way to pass props into handlers, but landing #374 for advanced uses (e.g. writing libraries that build off of RR)?

As soon I have permission to do so, I intend to open-souce my library for the good of the greater React community, so this is about more than some crazy guy doing a demo. (If I wasn't so concerned about keeping the concerns separate so I can open-source this later, I'd have found a solve that didn't rely on #374.)

I know it's crazy, but please let me know if it's something worth entertaining.

@appsforartists
Copy link
Author

I'll even rename it _handlerProps. 😃

@mjackson
Copy link
Member

@appsforartists You don't need handlerProps! :)

If you need a "global" settings object like the one you're describing, you can just use plain JS to solve your use case. Check this out:

With handlerProps:

var Home = React.createClass({
  // This is your route handler.
});

function makeTheRoutes(environmentData) {
  var settings = makeTheSettings(environmentData);

  return (
    <Routes handlerProps={{ settings: settings }}>
      <Route handler={Home}/>
    </Routes>
  );
}

Without handlerProps:

function createHomeHandler(environmentData) {
  var settings = makeTheSettings(environmentData);

  return React.createClass({
    // This is your route handler.
  });
}

function makeTheRoutes(environmentData) {
  return (
    <Routes>
      <Route handler={createHomeHandler(environmentData)}/>
    </Routes>
  );
}

It's basically the same thing that @rpflorence said here. If you want to automatically pass the settings object down through your component hierarchy, that's what this.context is for.

I'm sorry but I just can't see the necessity for handlerProps right now. Perhaps at some point in the future we'll think of a real need for them, but I don't see it now.

Thanks for your work on this tho! Really, I appreciate it.

@mjackson mjackson closed this Oct 16, 2014
@lock lock bot locked as resolved and limited conversation to collaborators Jan 21, 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.

3 participants