-
-
Notifications
You must be signed in to change notification settings - Fork 10.6k
Routes rendered by a component? #262
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
Comments
We're really close on server-side rendering and then maybe there will be a better way to integrate with react-rails, but for now you're going to have to figure something else out :( |
Oh, forgot to answer the question.
|
Funny I don't even get the error from Route Thanks for the confirmation, I'll try to figure out something else then :\ |
Can you maybe explain why If you have the time, I'd really love to understand the difference with a regular component... thanks! It's just out of pure curiosity and will to understand what's going on under the hood. I have figured out that since there's no server-side rendering at all, I can reasonably include a |
I'm not sure why exactly it doesn't work, but the design of this router is to be the thing that kicks off your app, not to be embedded in another app. |
Yep I understood that, but what's the real difference between calling The fact that it doesn't work is quite counter-intuitive for me :| |
@olance It's a little odd, I grant you. But the reason we used it is because the XML-like syntax of JSX makes it really easy to quickly scan the nesting of your routes and their relationship to one another. |
yeah but what about |
@olance Hmm ... I actually think that should work. Off the top of my head I can't think of any reason it shouldn't... :) |
Re-opening since I think @olance has a good point |
Ah! Well... it doesn't :D |
thanks! 👍 |
:/ Sorry you spent a whole night on it. As @rpflorence mentioned, we never intended |
Ah, no worries! It's not your fault, I just wanted it my way ;) |
Absolutely. I still need to think about it a little more and discover why it's failing in the first place, but as I said I don't see any reason right now why it shouldn't work. I'll look into it :) |
Thanks a bunch :) Not sure it'll help you though ^^ |
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.
Hi @olance Was you able to get the routes working with rails ? Thanks |
@gauravtiwari nope. I have left the subject for later, as I had other things to work on that were a bit more urgent for me. Now that the server-side rendering is ready, I guess this bug will come in focus again shortly... @mjackson any news? :) |
Thanks @olance. Yeah, server side rendering is working great from a while now. I actually integrated this small library called page.js for routing and it's working pretty well however, it will be good to have something that is built for react. Hopefully, it will be fixed soon. Thanks for your reply. |
hmm interesting, so are you using React-router on the server side and page.js on the client side for the moment, or are you waiting for react-router to have this bug fixed to use it? |
@olance React router is not working at all. I encountered many bugs while using it (not sure, it may be just me). So basically, I used page.js to render components by passing params or objects as a props to that component. One can do like - componentDidMount: function () {
var self = this;
page('/posts/:id', function (data) {
self.setState({ component: <PostShow data = {data Or whatever prop or state} /> });
});
page.start();
},
render:function() {
return (
{this.state.component} //this changes with data
)
} You can then have a list of post on a master component and just navigate around by passing data(props or states). I think one can achieve this together with rails on having the full-page rendered using server side on page reload and use page.js to navigate around sub-pages with client side routing and react. BTW, this one also looks interesting. I am experimenting with it - React router component |
in v0.11 this should work fine now. |
just realized we need a teardown (which I have a branch for already) for this to really work, will push soon, probably today. |
hey @rpflorence :) |
I have the code for this, need to push as soon as I'm done with this other thing I'm doing and then there's this yak also that I'm shaving ... |
Ahah okay, good luck with the yak then! ;) 🐃 |
thanks @rpflorence |
+1 |
@rpflorence any chance you could push your code to a branch while you're shaving that yak? Seems to be a few of us that might give it a look in the meantime. |
@rpflorence I'm running into something similar when trying to use react-router and Morearty. To see the problem in code, see here, or more discussion on the Morearty project here. Any idea if your solution will allow this? |
@olance I read part 1 of your blog post[1] about the server side rendering, and I was wondering why you never posted a part 2. Now, I see you've been stuck on the same thing I've been stuck with :) . I was wondering if you ever got this to work. Thanks! |
@krashidov yeah I've been stuck on this indeed, plus I haven't had so much free time to investigate and write the second part! :( @rpflorence I'd +1 @eikeon on this, maybe we could have access to your working branch for this and help a bit? |
What is your problem exactly? Current version of router lets you render whenever you want (code taken from this issue): // This is a reference to my Morearty binding object.
var binding = ...;
// Keep a reference to the "current handler", which is the React component
// class that is at the root of your route hierarchy.
var CurrentHandler;
function renderTheCurrentHandler() {
React.render(<CurrentHandler binding={binding}/>, document.body);
}
binding.addListener(function () {
// This is my notification that something in the binding changed.
renderTheCurrentHandler();
});
Router.run(routes, function (Handler) {
// This is my notification that the route changed.
CurrentHandler = Handler;
renderTheCurrentHandler();
}); |
@gaearon my problem is described in the first post for this issue ;) Apparently @rpflorence still has some work to do on the codebase to make it all work. However, I have not tested again since the last numerous improvements to the component. |
@olance That's why I was asking: you can do this now since 0.11.x. For example, see #547 (comment). However I still don't understand why you want to do that. It's way easier to make App top-level route and use router's nesting feature. Have you read about it? https://github.com/rackt/react-router/blob/master/docs/guides/overview.md#with-react-router |
Thanks for the link @gaearon, it should help me out :) I have read about it, but what I'm trying to achieve would be much nicer with a simple wrapper.
Using react-rails implies using the I'll try to get back at testing all this during the week and see what happens! ^^ |
With 0.11.x you can do it like this now: http://jsbin.com/duyaxa/1/edit?html,js,output |
thanks @rpflorence! Will this work server side as well together with react-rails gem ? |
I don't know why it wouldn't, but I don't know anything about the react-rails gem. |
Works well with react-rails gem! :) If you use something like return Handler ? <Handler initialState={this.props.initialState} /> : null; And then deeper in the route hierarchy in similar fashion: <RouteHandler initialState={this.props.initialState} /> |
The problem with the top level Prerender is very useful feature for SEO. It would be nice to be able to kick off the router when Javascript is enable and default to the component itself otherwise. When I try this approach I get context errors ( @Attrck Could you explain a bit more how you implemented it? A gist would be awesome! |
@GabKlein @Attrck pre-rendering doesn't work, because context is lost. also react_ujs breaks it on the client. |
Actually sorry it's not an issue with react-rails. The issue is that we want to render the app before we created a router. Like in this case where the initial state already has a handler: http://jsbin.com/mirajedadi/1/edit?html,js,console @ryanflorence do you have an idea how to easily render the app before the router is run? Like a synchronous call to Router.run() that returns the HTML string of the set route. |
The problem would be to generate the proper |
I tried to build off your example but navigation doesn't seem to work. Clicking the |
@Attrck is that just me or the react-rails-router's README examples are absolutely unobvious ? |
@bbnnt I don't know react-rails very well because I only have done frontend development in our project. We only pass the initial state to React app with react-rails. Code snippet from @rpflorence solved the problem with that. We haven't tried pre-rendering yet. Actually I didn't notice earlier that this conversation was about server-side rendering 😄 |
This is how I have react-router working with react-rails. With react-rails helper, pre-render 'StaticRoute' component with an additional path prop. React-router will take care of rendering the right handler in execjs. var StaticRoute= React.createClass({
render: function(){
var RouteHandler = Router.run(routes, this.props.path, function(){});
return (
<RouteHandler {...this.props} path={undefined} />
);
}
}); After reviewing the code I noticed Router.run returns the router instance with the current handler, which can be used to render the actual component, keeping the router context intact. The callback function in run is needed for location change setup. Which is not needed for server side rendering. Execjs does not support async anyway. Even though SEO works well, the down side of this approach is, when react runs in the browser it gets confused because it is expecting 'Router' component, not the 'StaticRoute' component in dom. react-rails-ujs does the setup of this pre-rendered component. So before I run react-router in the browser, I remove all HTML from container, and let react do everything from scratch. |
I've literally spent hours on that and I've come to believe what I want is not (yet?) possible.
I probably have a bit of an uncommon setup: I am using React within a Rails application using react-rails and browserify-rails to get things working together.
Before trying to use react-router, I had the following setup (a sample/simple blog app):
The App component would initialize an app context, register a PostStore and dispatch an
initial_state
message to fill the store with posts fetched on the server when rendering the page.Using react-rails, all of this would render on the server and then be picked up by the React UJS script, simply by calling the
react_component('App', {initialState: @app_state})
view helper in my Rails layout.Now, I want to display a
<PostShow>
component instead of my<PostsList>
when the user clicks on a post title. I chose to try react-router to handle the route changes and UI updates implied after talking to @mjackson on IRC ^^Because I am using react-rails, what I'd like to do is keep this unique entry point through my App component and the
react_component
call.So I have renamed
App
toAppRouter
and changed the render code of this main component to draw my routes instead:(I originally had a parent
<Routes location="history">
but have removed it after reading #40... not sure that was the right thing to do?)The new
App
component usesactiveRouteHandler
to display<PostsIndex>
or<PostShow>
depending on the active route.I really, really thought the would work out nicely, but I keep getting this error:
AppRouter.render(): A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object
Apparently,
<Route(s)>
isn't a React component. Is it not??!The codebase is quite large but I did find that
Routes = React.createClass(...)
so why would React tell me it's not a ReactComponent?What have I missed? Is there a way to achieve what I've described here?
The text was updated successfully, but these errors were encountered: