Skip to content

Commit

Permalink
[fix] Prevent needless prop updates causing rerenders (#5671)
Browse files Browse the repository at this point in the history
* [fix] Prevent needless prop updates causing rerenders

Fixes #5247 by not adding unchanged layout or page props to the root props

* enhance test

* spaces -> tabs, and add explanatory comment so we dont later delete it

Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
Co-authored-by: Rich Harris <hello@rich-harris.dev>
  • Loading branch information
3 people authored Jul 25, 2022
1 parent 2315d7e commit 66d17af
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/nasty-falcons-ring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

Prevent needless prop updates causing rerenders
7 changes: 5 additions & 2 deletions packages/kit/src/runtime/client/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -424,8 +424,11 @@ export function create_client({ target, session, base, trailing_slash }) {
};

for (let i = 0; i < filtered.length; i += 1) {
const loaded = filtered[i].loaded;
result.props[`props_${i}`] = loaded ? await loaded.props : null;
// Only set props if the node actually updated. This prevents needless rerenders.
if (!current.branch.some((node) => node === filtered[i])) {
const loaded = filtered[i].loaded;
result.props[`props_${i}`] = loaded ? await loaded.props : null;
}
}

const page_changed =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script context="module">
/** @type {import('@sveltejs/kit').Load} */
export async function load({ session }) {
session; // not necessary, but prevents the argument from being marked as unused
return {
props: {
// Needs to be an object, else Svelte will do by-value-comparison and skip rerender
obj: {}
}
};
}
</script>

<script>
import { session } from '$app/stores';
/** @type {any} */
export let obj;
let count = 0;
$: obj && count++;
</script>

<h1>{count}</h1>
<button on:click={() => ($session.calls = 123)}>Rerun Layout Load Function</button>
<slot />
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<h2>On a</h2>
<a href="/load/layout-props/b">to b</a>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<h2>On b</h2>
<a href="/load/layout-props/a">to a</a>
9 changes: 9 additions & 0 deletions packages/kit/test/apps/basics/test/client.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,15 @@ test.describe('Load', () => {
expect(await page.textContent('h1')).toBe("I didn't break!");
});

test("layout props don't cause rerender when unchanged", async ({ page, clicknav }) => {
await page.goto('/load/layout-props/a');
expect(await page.textContent('h1')).toBe('1');
await clicknav('[href="/load/layout-props/b"]');
expect(await page.textContent('h1')).toBe('1');
await page.click('button');
expect(await page.textContent('h1')).toBe('2');
});

if (process.env.DEV) {
test('using window.fetch causes a warning', async ({ page }) => {
const port = 5173;
Expand Down

0 comments on commit 66d17af

Please sign in to comment.