outlandishideas/kasia

How to properly preload within another saga

MickeyKay opened this issue · 5 comments

Hi there,

I have the following setup, in which everything is server-side-rendered:

  • A single higher-order Article component which preloads a query for article data. This data includes ids for commentIds.
  • A Comments child component, which takes the commentIds prop and preloads a query for comment data.
  • In our SSR data-dependency hook, we run the following:
const preloaders = [
  () => preload([Article], renderProps),
];
return runSagas(store, preloaders)

The Article component is decorated with a getArticleData saga ala:
@connectWpQuery(getArticleData, shouldUpdate)

Within the getArticleData saga, we somehow also need to preload our comments data. I've tried doing the following within that saga, but it is not working:

// Fetch article data (works!)
const article = yield doArticleFetch(...);

// Fetch comments data
yield preload(
  [Comments],
  { commentIds: getCommentIds(article) },
  state
);

. . . and where the Comments component looks something like this:

function* getCommentsData(props) {
  return yield fetchCommentsData(props);
}

@connectWpQuery(getCommentsData, shouldUpdate)
class Comments extends Component {...}

I can see that the fetch is being run and the response looks good if I log from within the top-level getArticleData saga, however the results are not being added to the store.

Calling runSagas works well in our primary saga, but manually calling preload does not appear to be actually populating the store (we've chosen this method because store is not currently accessible in the saga context - we could update this, however before doing that I'd like to understand if preload should be working). It's unclear to me whether I'm missing a required piece of the puzzle, however from reading the docs it looks as though we should just be able to call preload without anything else.

Can you please clarify what's missing, and perhaps provide an E2E example that uses preload instead of just runSagas?

Thanks!

Bump ❓

@sdgluck any word here? Apologies for pressing, however this is now something we've got two use cases for so I'll be diving in shortly.

Hey, apologies for the delay in responding.

I have added a test which I think covers what you are asking: https://github.com/outlandishideas/kasia/blob/master/test/util/preload.js#L129

(See this component too, which uses preload of another Kasai component.)

Take a look and tell me if what you're doing is different and how?

A minimal reproducible example would help if you have the time.

@MickeyKay

I've noticed that you are not calling the result of your call to preload.

Like this:

    yield preload(
      [Comments],
      { commentIds: getCommentIds(article) },
      state
    )();
//-->^^

preload returns a generator which needs to be "started" before you yield to it. The reason for this is that usually when you are calling preload in the context of runSagas we don't want to actually preload at the time of calling preload, but defer the execution of preloading to the runSagas fn where we can pass the current state of the store to each preloader (as per example in docs).

(See this line for an example in the aforementioned tests.)

Looks like the docs are incorrect/misleading on this. Sorry about that.

Aha, worked! Thank you!!!