-
-
Notifications
You must be signed in to change notification settings - Fork 10.4k
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
Proposal: Replace AsyncState with getAsyncProps #261
Comments
👍 if (!singleRun) {
this.userListener = function () {
setProps({ user: UserStore.getUserByID(params.userID) });
};
UserStore.addChangeListener(this.userListener);
} Looks sorta bleh, but it could easily be wrapped up and made declarative based on the architecture of an individual application, like mapping async props to stores by key with a mixin etc. // I dunno, something like this would totally be possible
var SomeHandler = React.createClass({
mixin: [FluxBBQ({
users: UserStore,
assignments: AssignmentStore
})]
}); Good that the router doesn't get too interested in application conventions. |
I almost wrote it like: UserStore.addChangeListener(this.userListener = function () {
setProps({ user: UserStore.getUserByID(params.userID) });
}); A little more concise :) But yeah, the router needs to be pretty generic so your app can do whatever it wants. |
Do you mean |
@ewiner Yes, thanks for pointing that out. My brain is fried from thinking about this too much.. |
I wouldn't mind supporting the use cases described in #176, namely, leaving the previous screen rendered while these transition hooks resolved, via an option on |
@rpflorence Interesting. So basically just a flag that gives you fine grained control over when you actually want things to update? The way I see it there are two options:
What's the main use case for the second? To prevent flickering while data loads? What about the delay in navigation? |
The |
I'm indifferent about props vs. state and like avoiding needing to declare a mixin. |
Why is there a |
( |
@spicyj The important thing to note is that you don't actually have to use it. In fact, it should probably be the last argument to The way the router is built, all data is passed in as props (think |
@KyleAMathews Up to this point people have been using |
|
I just picked these names because they correlate directly with the |
@rpflorence BTW, I should mention that it would be trivial to implement #176 using the architecture I've got going (been hacking on this today). Just kind of seems like a footgun. |
I think it's valid. Lots of apps do this and it feels fine. Gmail, google analytics, some parts of Facebook, even some native iPhone apps I use. Sent from my iPhone
|
@rpflorence ok. Let's discuss in a separate issue. |
In React's core API, the will* and did* methods are intended for doing side effect operations with no return value before or after some built-in action, while the get* methods are intended for you to return some data that the library will then use.
I didn't suggest |
I like @ewiner's names. |
(though, willTransitionFrom is as good a place as any for that ...) |
@rpflorence @mjackson why can't we just continue using |
@rpflorence @KyleAMathews @ewiner yeah, something like
|
/me casts a vote:
|
yeah @rpflorence 👍 |
How will this deal with errors in fetching data? You will want a way of passing those errors (from the promises) as props also. |
@taurose Flux is an anti-pattern when it comes to the server. Stores just don't make sense in a stateless environment. I've been struggling to make it work for a while now, but there are a lot of things that just don't make sense (including actions, dispatchers, etc.) @appsforartists So, initially we were using state for storing data. But that doesn't work for server-side rendering because the environment is inherently stateless, so we need to put all the data in props. |
@mjackson @taurose I've been using yahoo/dispatchr, which solves the problem of server-side singleton stores by... well.. by not being a singleton. I instantiate a new Flux for each request on the server, call a few actions to set up the data in the right way, then use the |
@mjackson I like it, I've been kind of yearning to go in that direction also.
This is not a problem the router has to solve. The router is providing an API to:
It's up to not-the-router to figure out how that works with your data. |
@mjackson @rpflorence I agree - the router should provide an API not be a data store. |
I think this represents a typical use-case with something like flux: var Courses = React.createClass({
statics: ENV.SERVER ? {
// only defined for the server
getAsyncProps: function() {
return {
courses: db.getCourses()
};
}
} : {},
getInitialState: function() {
return {
// slurp up state from props if they are there
courses: this.props.courses || []
};
},
getStateFromStores: function() {
return {
courses: CourseStore.getState()
};
},
// only called on the client
componentDidMount: function() {
CourseStore.addChangeListener(this._onchange);
},
componentWillUnmount: function() {
CourseStore.removeChangeListener(this._onchange);
},
_onchange: function() {
this.setState(this.getStateFromStores());
},
render: function() {
return (
<div>
<h1>Courses</h1>
<CourseList course={this.state.courses.length}/>
</div>
);
}
}); We might not even need the (I don't think I'd care to make my stores work isomorphically, I'd rather just do what that code does) |
Sorry I wasn't clear. I was talking about the stores in react-router which would cause problems when rendering (resolving async props for) more than one route at the same time as far as I can tell. I didn't mean to take this off-topic though 😄 |
I think we've already refactored that code already for that reason. Sent from my iPhone
|
@taurose I've already prepped the PathStore for server-side work, RouteStore still needs some work tho. But after @ewiner's comment, I'm taking a closer look at yahoo/dispatchr which seems like a better fit for server-side work. |
@rpflorence Yeah, I like your example. Let's strip the whole thing down to just |
Just realized: we should also deprecate/remove "static" props that are passed to |
@mjackson I take it you're talking about removing the ability to go
I'm working on a project using ReactRouter on both the client and server, and I'm trying to find the right way to pass data into the route tree. I've put together a library called Ambidex that takes a set of In this project, each domain is effectively running the same app with some minor configuration changes. I need to be able to access those changes from within the common app's components to make sure to render the correct variant. Here's a flowchart, though I'm not sure if it's helpful:
The settings for each instance are generated dynamically, but the common app can only I tried having the common app call If I could use On the client, I'd just close-over the appropriate settings to make sure they're always in-scope. Unfortunately, I don't know of any way to pass local scope into another module in Node. I'd love some advice here. Is there a good way of passing props into a view when it's being rendered on the server? Anything else jumping out at you that could be a good solution? Please let me know if there's anything I can clarify. It's hard to explain all this in a comment field on a Friday evening if you haven't seen the app. 😃 Thanks! |
@appsforartists I'd recommend against using |
Thanks @mjackson. It's just a prototype for now, so I'm not too concerned about stability yet. I'm more interested in figuring out how to pass data down from my server into the route handlers, so I'll be ready when Do you have any input there? |
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.
Hey, guys. I'm the author of dispatchr and I'd love to help where I can. We're using dispatchr and other libraries to handle routing right now but we like the syntactic sugar the react-router gives within components to define routes and determine subcomponents rather than handling that outside of React. To give you some ideas of how we're handling server and client flux flows, you can see our flux-examples repo, specifically the routing example. @mjackson I think there's room to converge on some of our ideas here. |
Geez, all these comments and now the whole story around props has changed with 0.11 (see the upgrade guide). I'm gonna close this for now, but thank you everyone for your contributions to the conversation. @mridgway Welcome to react-router :) If you'd like to get involved, please do! We can always use more help. We try to keep on top of the GH issues as much as possible in the hopes that it will be easy for newcomers to see where they can pitch in if they'd like to. The vast majority of conversation around this project happens on GH and in the #rackt channel on freenode. Happy hacking! :) |
Edit: Please read my updated proposal as well
I'd like to propose adding two new transition hooks,
didTransitionTo
anddidTransitionFrom
that are designed to replace theAsyncState
mixin. Currently,AsyncState
has the following quirks/limitations:this.state
, but data is passed passed to children through props inrender
The goals for these two new transition hooks are:
this.state
should be used for UI stateI believe the following API satisfies all of the above requirements. Feedback is welcome.
Note that, although this API looks similar to the
willTransition*
API, it has two key differences:Thanks to @rpflorence for giving me feedback and helping me think through this API earlier today!
Edit: Updated example code to make
setProps
the last (optional) argument todidTransitionTo
.The text was updated successfully, but these errors were encountered: