Skip to content

Clarify conditions goto uses to call load #6788

@theetrain

Description

@theetrain

Describe the problem

While trying to make use of goto and invalidateAll, I couldn't get my page to call its load function predictably. It turns out, my page's load method had no dependencies that would trigger it to change, even though it's a navigational change with different params.


Details for those curious

My example project

The layout and page files are in this file structure:

  • src/routes/[branch]/+layout.svelte
  • src/routes/[branch]/+layout.server.js
  • src/routes/[branch]/thing/[id]/+page.svelte
  • src/routes/[branch]/thing/[id]/+page.server.js

The broken behaviour:

  • Given the current page is /main/thing/abc123
  • When the user clicks a button in a 'Switch branch' dropdown (kinda like GitHub branches)
  • Then it calls goto('/otherbranch/thing/abc123')
  • And the target [branch] param has changed, and [id] stayed the same.
  • But the target +page.server.js's load method was not called again

In +page.server.js, I have:

/** @type {import('./$types').PageServerLoad} */
export async function load ({ params, locals }) {
  if (!params.id) {
    // No id
    throw error(400, 'No ID provided')
  }

  // get db connection passed in from `src/hooks.server.js@handle`
  // which actually makes use of `params.branch` but isn't explicitly utilized in this `load`
  const { db } = locals

  // ... do db stuff

  return { rows }
}

It calls params.id, but it does not call params.branch, so I assume SvelteKit is aggressively optimizing this load to not invalidate if params.branch ever changes; and I was unaware. I made this adjustment, and now load runs after I call goto('/different-branch-from-before/thing/abc123'):

+ export async function load ({ params, locals, depends }) {
+   depends(params.branch) // this is probably wrong and I'm sorry

I came across this insightful comment: #1684 (comment)

It describes how goto calls a page (or layout's) respective load under the following conditions:

goto() will only run load() if page.params, page.path, page.query, session or context is used inside of load and one of those values has changed since the last run of the load function.

On the surface this makes sense, the load method needs to have some sort of changed params in order for goto to call it again. However, I could not find this behaviour in the docs, and I still have uncertainties:

  1. Does page.params refer to the $page store used on that load method's respective +page.svelte? Or does it (more likely) refer to event.params used in load?
  2. How do I tell my page and its parent layout to call load when goto navigates to that page?
  3. Is there a way to tell a load to always refetch values if the user navigates to it? I understand it's optimal to make use of depends, but I don't understand its functionality, either.
  4. How do I make use of depends so that if a path param changes, that load should invalidate? I assume it's depends(params.targetParam), but I don't know.

Describe the proposed solution

I'm happy to work with the team to add some details to the docs to better capture the behaviour of goto and when it would or would not call load on the target route, how to assign path params to depends within load, and any applicable side-effects of these features.

Alternatives considered

I guess I could do without the event.locals trickery and be more explicit with my dependencies in load, but I wanted to avoid some boilerplate.

Importance

would make my life easier

Additional Information

This comment was also very informative and parts of it should probably make it to the docs: #2560 (comment)

Specifically the detail on how hard copies of store values will get properly recognized as changed in SvelteKit's optimization logic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions