Skip to content

Page load functions should return props via derived stores #5850

@joeally

Description

@joeally

Describe the problem

Having a single load function which loads all of the data for a page means that you cannot reload part of the pages contents. If the user performs an action that invalidates part but not all of the page one has to reload the route which will fetch all of the data for the page. This means that the app will make more database and storage calls than necessary. If the props returned by the load function are not primitive values svelte will also re-render pretty much the entire page even if only a single only component needs updating. Because even if the returned props have equal values svelte is only able to check equality for primitive values.

This means that to get partial updates in pages we have to duplicate the load logic in event handlers in the page. The partial updates however will not be available to users with no Javascript so the developer is forced to handle that case separately. It would be much better if load only made the fetches that it needed to based on its inputs.

Describe the proposed solution

Instead of the load function returning a props object with a value specified for each component prop the load function should instead return a props object with a store specified for each component prop. This would also require that objects passed into the load function are stores.

Consider the following example load function in my proposed 'store style' for a hypothetical (and somewhat contrived) social network example where the user navigates between posts but and the user's profile information is displayed in the top corner of each page.

export const load = ({ request, stuff, url, session, status, error, params, fetch }) => {
  const post = derived([params], async ([$params], set) => {
    const postResponse = await fetch(`posts/${params.postId}.json`);
    const postData = await postResponse.json();
    set(postData);
  });
  const userProfile = derived([session], async ([$session], set) => {
    const userProfileResponse = await fetch(`userProfile.json?sessionId${$session.sessionId}`);
    const userProfileData = await userProfileResponse.json();
    set(postData);
  });
  return {
    props: { post, userProfile }
  }
}

Every time the user navigates to a different post the params store is updated causing the new post data to be fetched using the new postId. Any components that depend on the post prop will then be updated. However because the session has not changed the user profile does not need to be refetched. And since the userProfile store does not get updated any components that only depend on the userProfile prop don't need to be updated.

Alternatives considered

No response

Importance

would make my life easier

Additional Information

No response

Edit: Fixed some errors in my writing. I was a bit tired when I wrote this.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions