Přichází zapisovatelné $derived

May 14, 2025
Bindování $derived
Protože do hodnot odvozených runou $derived
nelze zapisovat, nelze je ani bindovat. Lze to řešit pomocnou proměnnou
vytvořenou $state
runou ze závislé hodnoty. V případě komplexnější komponenty tak počet proměnných narůstá a
čitelnost se snižuje. Nehledě na nutnost vymýšlet další a další jména, což je vážně děs.
<script>
/**
* @type {{
* names: { first: string, last: string },
* saveNames: (first: string, last: string) => Promise<void>
* }}
*/
let {names, saveNames} = $props()
let isSaving = $state(false)
let fullName = $derived(`${names.first} ${names.last}`)
let editableName = $state(fullName)
let isChanged = $derived(editableName !== fullName)
function handleSave() {
isSaving = true
let [first, last] = editableName.split(' ')
saveNames(first, last)
.finally(() => isSaving = false)
}
</script>
<div>
<b>Name:</b>
<span contenteditable bind:textContent={editableName}></span>
{#if isChanged && !isSaving}
<button onclick={handleSave}>save</button>
{:else if isSaving}
<i>saving...</i>
{/if}
</div>
Zapisovatelné $derived
Verze 5.25 toto mění přidáním možnosti zapisovat do odvozené hodnoty, čímž zjednodušuje kód i práci a zlepšuje čitelnost.
<script>
/**
* @type {{
* names: { first: string, last: string },
* saveNames: (first: string, last: string) => Promise<void>
* }}
*/
let {names, saveNames} = $props()
let isSaving = $state(false)
let fullName = $derived(`${names.first} ${names.last}`)
let isChanged = $derived(fullName !== `${names.first} ${names.last}`)
function handleSave() {
isSaving = true
let [first, last] = fullName.split(' ')
saveNames(first, last)
.finally(() => isSaving = false)
}
</script>
<div>
<b>Name:</b>
<span contenteditable bind:textContent={fullName}></span>
{#if isChanged && !isSaving}
<button onclick={handleSave}>save</button>
{:else if isSaving}
<i>saving...</i>
{/if}
</div>
Zajímavé je, že read-only
nebylo kvůli nějaké technické překážce, ale bylo vytvořeno úmyslně. Implementace tak
obnášela hlavně mazání kódu.