mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
fix(panel): derive the retention input instead of syncing it in an effect
The Transcript Retention card seeded its input from the settings query with a useEffect + setState, which trips react-hooks/set-state-in-effect (cascading renders). Derive the displayed value (edited ?? serverValue) during render instead; the user's edits live in 'edited', reset to null after a successful save so the field re-syncs to the server value. No effect, no setState-in-effect.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useState } from "react";
|
||||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
import { settingsApi } from "@/lib/api";
|
import { settingsApi } from "@/lib/api";
|
||||||
import {
|
import {
|
||||||
@@ -21,24 +21,24 @@ const DEFAULT_RETENTION = "14";
|
|||||||
|
|
||||||
export function TranscriptRetentionCard() {
|
export function TranscriptRetentionCard() {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const [days, setDays] = useState<string>(DEFAULT_RETENTION);
|
// `edited` holds the user's in-progress input; null means "show the server
|
||||||
|
// value". Deriving the displayed value avoids syncing query state into local
|
||||||
|
// state with an effect (react-hooks/set-state-in-effect).
|
||||||
|
const [edited, setEdited] = useState<string | null>(null);
|
||||||
|
|
||||||
const { data: settings, isLoading } = useQuery({
|
const { data: settings, isLoading } = useQuery({
|
||||||
queryKey: ["settings"],
|
queryKey: ["settings"],
|
||||||
queryFn: settingsApi.getAll,
|
queryFn: settingsApi.getAll,
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
const serverValue = settings?.[RETENTION_KEY] ?? DEFAULT_RETENTION;
|
||||||
const stored = settings?.[RETENTION_KEY];
|
const days = edited ?? serverValue;
|
||||||
if (stored !== undefined) {
|
|
||||||
setDays(stored);
|
|
||||||
}
|
|
||||||
}, [settings]);
|
|
||||||
|
|
||||||
const saveMutation = useMutation({
|
const saveMutation = useMutation({
|
||||||
mutationFn: (value: string) => settingsApi.update(RETENTION_KEY, value),
|
mutationFn: (value: string) => settingsApi.update(RETENTION_KEY, value),
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ["settings"] });
|
queryClient.invalidateQueries({ queryKey: ["settings"] });
|
||||||
|
setEdited(null); // re-sync the input to the freshly-saved server value
|
||||||
toast.success("Transcript retention updated");
|
toast.success("Transcript retention updated");
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
@@ -79,7 +79,7 @@ export function TranscriptRetentionCard() {
|
|||||||
min={1}
|
min={1}
|
||||||
value={days}
|
value={days}
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
onChange={(e) => setDays(e.target.value)}
|
onChange={(e) => setEdited(e.target.value)}
|
||||||
className="max-w-[160px]"
|
className="max-w-[160px]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user