fix: sync reactive state with data prop using \$effect

Replaces bare \$state(data.x) initialisers (which only capture the
initial value) with \$state + \$effect pairs so that state stays in sync
whenever page data is invalidated or the URL changes. Affects all list
pages (searchValue) and all edit/detail pages (form fields).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 11:06:30 +01:00
parent dc1850126b
commit b9b98f178f
13 changed files with 60 additions and 0 deletions

View File

@@ -21,6 +21,7 @@
let deleteOpen = $state(false);
let deleting = $state(false);
let searchValue = $state(data.search ?? "");
$effect(() => { searchValue = data.search ?? ""; });
let searchTimeout: ReturnType<typeof setTimeout>;
function debounceSearch(value: string) {

View File

@@ -28,6 +28,20 @@
);
let imageId = $state<string | null>(data.article.image ?? null);
let authorId = $state(data.article.author?.id ?? "");
$effect(() => {
title = data.article.title;
slug = data.article.slug;
excerpt = data.article.excerpt ?? "";
content = data.article.content ?? "";
category = data.article.category ?? "";
tags = data.article.tags ?? [];
featured = data.article.featured ?? false;
publishDate = data.article.publish_date
? new Date(data.article.publish_date).toISOString().slice(0, 16)
: "";
imageId = data.article.image ?? null;
authorId = data.article.author?.id ?? "";
});
let selectedAuthor = $derived(data.authors.find((a) => a.id === authorId) ?? null);
let saving = $state(false);
let editorTab = $state<"write" | "preview">("write");

View File

@@ -18,6 +18,7 @@
let deleteOpen = $state(false);
let deleting = $state(false);
let searchValue = $state(data.search ?? "");
$effect(() => { searchValue = data.search ?? ""; });
let searchTimeout: ReturnType<typeof setTimeout>;
function debounceSearch(value: string) {

View File

@@ -19,6 +19,7 @@
let deleteOpen = $state(false);
let deleting = $state(false);
let searchValue = $state(data.search ?? "");
$effect(() => { searchValue = data.search ?? ""; });
let searchTimeout: ReturnType<typeof setTimeout>;
function debounceSearch(value: string) {

View File

@@ -16,6 +16,7 @@
const { data } = $props();
let searchValue = $state(data.search ?? "");
$effect(() => { searchValue = data.search ?? ""; });
let searchTimeout: ReturnType<typeof setTimeout>;
let deleteTarget: User | null = $state(null);
let deleteOpen = $state(false);

View File

@@ -24,6 +24,15 @@
let photoId = $state<string | null>(data.user.photo ?? null);
let isAdmin = $state(data.user.is_admin ?? false);
let saving = $state(false);
$effect(() => {
firstName = data.user.first_name ?? "";
lastName = data.user.last_name ?? "";
artistName = data.user.artist_name ?? "";
avatarId = data.user.avatar ?? null;
bannerId = data.user.banner ?? null;
photoId = data.user.photo ?? null;
isAdmin = data.user.is_admin ?? false;
});
async function handleAvatarUpload(files: File[]) {
const file = files[0];

View File

@@ -18,6 +18,7 @@
let deleteOpen = $state(false);
let deleting = $state(false);
let searchValue = $state(data.search ?? "");
$effect(() => { searchValue = data.search ?? ""; });
let searchTimeout: ReturnType<typeof setTimeout>;
function debounceSearch(value: string) {

View File

@@ -29,6 +29,20 @@
let selectedModelIds = $state<string[]>(
data.video.models?.map((m: { id: string }) => m.id) ?? [],
);
$effect(() => {
title = data.video.title;
slug = data.video.slug;
description = data.video.description ?? "";
tags = data.video.tags ?? [];
premium = data.video.premium ?? false;
featured = data.video.featured ?? false;
uploadDate = data.video.upload_date
? new Date(data.video.upload_date).toISOString().slice(0, 16)
: "";
imageId = data.video.image ?? null;
movieId = data.video.movie ?? null;
selectedModelIds = data.video.models?.map((m: { id: string }) => m.id) ?? [];
});
let saving = $state(false);
async function handleImageUpload(files: File[]) {