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

[SSR] getDataFromTree ignores (doesn't wait for) queries triggered after loading first queries #94

Closed
zenflow opened this issue Sep 17, 2019 · 1 comment · Fixed by #97

Comments

@zenflow
Copy link
Collaborator

zenflow commented Sep 17, 2019

Sometimes we have a component that makes a query then renders some component(s) that makes more queries.

Currently getDataFromTree does not fulfill those queries that are made after the first query(s) are done. The page is server-rendered while all queries beyond the first "layer" are still not loaded. The second layer of queries is actually triggered [server-side] by the second and final rendering of the react element tree, but the results come after the page has been sent.

You can see this issue in action in my branch for #93 . When page opens in browser, the list(s) are populated, but the "Assignee" for each list item is still "Loading...".

This is a problem when you want to take advantage of SSR while taking the approach of using components (or groups of components) that declare their own data dependencies (e.g. PR #93) rather than the approach of depending on data that was fetched in one monolithic (i.e. for every element on the page) request by code somewhere up the hierarchy of react elements. In this [first, components-requesting-their-own-data] case you would typically have multiple "layers" of queries to make. (Hopefully at some point we will be able to opt-in to batching queries together in each layer (#4), or at least have them deduplicated automatically, which seems straightforward & uncontroversial enough.)

This is something that works in apollo, as you can see from inspecting it's getDataFromTree implementation: process() (which includes rendering tree) calls itself recursively while hasPromises().

So in a similar fashion, we should in our getDataFromTree implementation probably be, after awaiting promises, re-rendering and checking for more promises. Something like:

export async function getDataFromTree<STORE extends typeof MSTGQLStore.Type>(
  tree: React.ReactElement<any>,
  client: STORE,
  renderFunction: (
    tree: React.ReactElement<any>
  ) => string = require("react-dom/server").renderToStaticMarkup
): Promise<string> {
  while (true) {
    const html = renderFunction(tree)
    if (client.__promises.size === 0) {
      return html
    }
    await Promise.all(client.__promises)
  }
}

But if you are using the default fetchPolicy "cache-and-network" for your queries, that will cause an infinite loop, since each rendering will cause a network request for every query, including ones that have already been requested and cached.

Apollo deals with this (as well as the next issue I am about to document) by, depending on ssrMode & ssrForceFetchDelay options, forcing fetchPolicy to "cache-only" for queries with one of the fetch policies that always uses network.

The semantics of those options are that ssrMode: true disables network fetch policies for good, while using ssrForceFetchDelay: 100 will disable them for 100ms and then start allowing them. I think we could simplify this:

I propose that when the existing ssr [client constructor] option is true, we disable network fetch policies (by forcing the policy to "cache-first" as needed) only during server-side rendering and initial client-side re-rendering, and, without needing to opt-in via a ssrForceFetchDelay, after that allow use of whatever fetch policy developer wants.

@mattiasewers @chrisdrackett What do you think? Happy to put in a PR for this!

@zenflow zenflow changed the title [SSR] getDataFromTree ignores queries triggered by loading other data [SSR] getDataFromTree ignores (doesn't wait for) queries triggered after loading first queries Sep 17, 2019
@mtsewrs
Copy link
Collaborator

mtsewrs commented Sep 18, 2019

@zenflow sounds resonable, I don't think I have time this week but PRs are always welcome!

chrisdrackett added a commit that referenced this issue Sep 23, 2019
Fix SSR issues #94 & #95 & (somewhat incidentally) bug #91
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants