Let's say I have a component:
<script lang="ts">
const players: Player[] = getPlayersFromSomewhere()
</script>
{#each players || [] as player}
<Player {player} />
{/each}
<script lang="ts">
export let player: Player;
async function doSomethingWithPlayer() {
// many lines of code here...
}
async function doSomethingElse() {
// many lines of code here...
}
async function doSomethingElseAgain() {
// many lines of code here...
}
// ... many functions here
</script>
player is used here with many buttons like:
<button on:click={doSomethingWithPlayer}>...</button>
<button on:click={doSomethingElse}>...</button>
<button on:click={doSomethingElseAgain}>...</button>
Is Svelte recreating the functions in Player.svelte for each player or just one time using it for each player?
Shall I create the functions in Page.svelte and pass them to Player.svelte? Or is Svelte able to "hoist" them?
Svelte will automatically hoist functions that don't depend on local component state. From the docs:
Don't worry about the fact that we're redeclaring the foo function for every component instance — Svelte will hoist any functions that don't depend on local state out of the component definition.
You can see this behavior in the Svelte REPL. Consider the following component.
<script>
let name = 'world';
function changeName() {
name = name + 1;
}
function log() {
console.log("I'm independent")
}
</script>
<h1>Hello {name}!</h1>
<button on:click={changeName}>
Change
</button>
<button on:click={log}>
Log
</button>
changeName depends on component state, but log does not, so it is hoisted out of the component. You see the following in the compiled JS: there is only one log function, but changeName is created per instance.
function log() {
console.log("I'm independent");
}
function instance($$self, $$props, $$invalidate) {
let name = 'world';
function changeName() {
$$invalidate(0, name = name + 1);
}
return [name, changeName];
}
class App extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance, create_fragment, safe_not_equal, {});
}
}
You could use the module context to run code only once regardless of how many times you initialize the component. I recommend you look at this answer from Rich Harris and the official module context tutorial.