-
Notifications
You must be signed in to change notification settings - Fork 27.6k
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
Need to manually re-call getInitialProps of sub-components #192
Comments
I think this is mainly an issue when using a HOC to wrap page components, e.g. for adding a navigation bar or site wide footer etc. Perhaps if we went down the route being discussed in #88, where a user could supply a global component ( |
You can write your page components with HOC like the following: import React from 'react'
import hoc from '../components/Hoc'
const Component = hoc((props) => <div>{props.value}</div>)
Component.getInitialProps = () => {
return { value: 'my value' }
}
export default Component I think there is no much difference whether if you use HOC or not. |
I agree, but if it's a sub-component which is wrapped in a HOC (in my case, an Apollo HOC), then this page will have to make sure to call it from here, otherwise the effects are unpredictable. It took me time to figure out these subtle bugs, I wouldn't wish every newcomer to have to figure it out the same way. For example here is my current working code, it already uses two HOCs, If I decide to change import React from 'react';
import Users from '../containers/Users';
import page from '../components/Page';
const Discover = () => (
<div>
<Users />
<div>other fancy stuff</div>
</div>
);
export default page(Discover); then I will get a cryptic error Don't get me wrong, I think Next.js is awesome 😄 but this makes it a bit hard to scale and leads to frustration. |
I agree that it'll be hard to figure out the bug. I think It'd be cool if we can display warning when |
That'd be cool, and I'd say if we can auto-detect, then we could as well call these |
@nkzawa you could probably traverse the component tree prior to calling |
I don't know much and haven't tried next.js yet, but if I remember correctly It seems like https://github.com/ericclemmons/react-resolver is doing something similar though without Don't know if this helps really but we never know. |
@dbismut |
@sedubois that's why |
@dbismut thanks yes, I didn't pay enough attention, I thought the project was inactive as no commit since 3 months. We should try to build an example. |
I checked how We'd have to do the same for supporting Maybe we can still display warnings by traversing the component tree after rendering (not before |
@nkzawa I might have misunderstood, but are you saying that we shouldn't be using For example, how would I bind my Apollo HOCs, without I'd want to ensure colocation, not having all async code gathering up in fat components at the root of the component hierarchy. |
nope, I meant next.js shouldn't try to handle So it seems we shouldn't add warnings too, if people'd like to merge |
@nkzawa as highlighted in previous comments and e.g in @luisrudge's implementation (improved by @impronunciable) of an authentication flow, (see commit), not only are we bound to repeatedly forget calling the child |
@nkzawa Manually handling children's If somehow feasible, the above example could be rewritten as: import connectInitialProps from 'next/connect';
const Child = ({ name }) => <div>{name}</div>;
const Child1 = connectProps(() => ({ name: 'Child1' }))(Child);
const Child2 = connectProps(() => ({ name: 'Child2' }))(Child);
export default () => (
<div>
<Child1 />
<Child2 />
</div>
); AFAIK Redux and Apollo allow that kind of thing thanks to their store provider. If Next doesn't want to force the use of a store, maybe we could find a middle ground where Next supports getting data from a store if one exists, otherwise works as before? (thinking out loud here) |
I agree with @sedubois here, the need for getting data deep in the component hierarchy isn't easily dismissed. Imagine for example a list of items, one of which should be "expanded" with more data. In the top getInitialProps you fetch the data for the list, and in the individual component's getInitialProps you'd check whether the component is expanded and load more data if needed. |
@nmaro the "ListItem" component could be passed additional props when it is expanded. With the addition of React's context you have everything you need to pass the data down. |
True @amccloud, but I see the following problems with this approach:
I mean, if (server-side-)rendering complex apps with modular data dependencies is out of the scope of next.js that's also fine, one just needs to say it. Right now I don't see a good pattern to handle this case. |
@nkzawa please correct me if I'm wrong:
|
@amccloud do you mean just passing down some context data, and then fetching the actual data down in the hierarchy? I don't think it's possible, of course would be great to hear otherwise. I believe all the async/data-fetching operations on the server have to happen in getInitialProps - which I think is the problem.
Imagine Component needs some graphql data with a query defined specifically for that component. |
Hi. I'm following the development of next with great interest and I wanted to chime in on this issue. In my opinion, architecting even a moderately complex web application while having to hoist each pages's data to the root component will be very hard to handle cleanly. If a solution can be found then it would be much better. Just off the top of my head, could each component simply await on data in the componentWillMount hook, therefore blocking the entire rendering process until all the data is available? Clearly we would only want to do this on the server, so perhaps an API can be exposed that components can use. |
@amccloud |
Anyway, this issue shows that it really is a problem with react, not next.js: facebook/react#1739 |
@nkzawa I didn't mean to imply that On the client we wouldn't want to use an await. We want do render everything that we can and update state/props once the data's available. next could provide an API to make that more seamless. |
@timothyarmes Unfortunately, you can't do |
Can we still explore using a store such as Redux as I'd love to have @arunoda's opinion, considering your interest in GraphQL. IMHO we need to properly solve this, otherwise Next won't be able to scale for all projects with data-connected components. |
How about @VanCoding's solution in facebook/react#1739 (comment)? See code. |
This issue seems trickier than it sounded. I'm curious about the developments around this, especially on the react side, but I believe that for the time being I'm going to settle for this pattern:
|
@nkzawa what happens if you try? Surely it should just look like a long synchronous call as far as React is concerned. |
@timothyarmes using await in |
Yeah, I wasn't thinking clearly. To use an await the function has to be declared async, and clearly we can't do that. |
Made a simple repo with a solution to this issue: |
Well, in the example, the parent does not handle the state. What I'm trying to achieve is bootstrap some stuff in the Application (in another project) and let the child handle data fetching (and injection with feathersjs) |
@nkzawa this issue now seems to be fixed! My need was for Apollo components and as pointed out by @ads1018 in #387 (comment), everything can be set up from the page root so that deeper components don't need any I updated my app: https://github.com/RelateNow/relate This might be closed I think. |
From this week's React Conf, after React Fiber (React 16) is out: Means async React lifecycle methods could be coming? Maybe that would make |
As described here: #159 (comment) and as far as I understand, if some React component has a
getInitialProps
, then all of its parents are condemned to need it too, and each parent in turn needs to callgetInitialProps
on their children, in the right order, making sure not to duplicate the work between the different levels of ancestry (the linked issue shows the case of a higher-component style, but the same applies when passing components as React children the normal way).Forgetting one of these calls can lead to silent bugs such as not having server-side rendering, and this code repetition can hinder proper componentization (one of React's key patterns).
From an end-user perspective, just like with React component lifecycle methods such as
componentWillMount
etc, IMHO the developer should trust thatgetInitialProps
will be called no matter what, as long as it's spelled properly.Could Next.js handle
getInitialProps
as part of the React component lifecycle or implement the same kind of magic to make sure it gets called whenever defined in a component?I'm new to SSR and Next.js, so apologies if this makes no sense 😄
The text was updated successfully, but these errors were encountered: