From 48b60fec54394e3b02bea66e3fb7cc3fb612540b Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Wed, 15 Jul 2026 06:01:33 +0200 Subject: [PATCH] fix(frontend): re-sync the sniffing island when its value changes externally The sniffing config editor froze its seed value at mount and only watched its own inner AntD form, never reflecting a later change to the shared RHF `sniffing` path. Because the inbound form mounts every tab with forceRender, the friendly Sniffing tab and the Advanced JSON editor are live at once: editing sniffing in the JSON editor updated the RHF value but not the frozen island, so the next interaction with the friendly tab emitted the stale value and silently discarded the JSON edit. Add an effect that pushes an external value change into the inner form, guarded by the same lastEmitted marker the emit path uses so the island never re-seeds from its own echo and no update loop forms. --- .../lib/xray/forms/fields/SniffingField.tsx | 8 +++++++ .../src/test/sniffing-field-resync.test.tsx | 21 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 frontend/src/test/sniffing-field-resync.test.tsx diff --git a/frontend/src/lib/xray/forms/fields/SniffingField.tsx b/frontend/src/lib/xray/forms/fields/SniffingField.tsx index 45ce5ad26..5369f8d99 100644 --- a/frontend/src/lib/xray/forms/fields/SniffingField.tsx +++ b/frontend/src/lib/xray/forms/fields/SniffingField.tsx @@ -27,6 +27,14 @@ export default function SniffingField({ value, onChange, enableLabel }: Sniffing onChangeRef.current?.(sniffing); }, [sniffing]); + useEffect(() => { + if (value === undefined) return; + const serialized = JSON.stringify(value); + if (serialized === lastEmitted.current) return; + lastEmitted.current = serialized; + form.setFieldsValue({ sniffing: value }); + }, [value, form]); + return (
{ + it('reflects an external value change (e.g. an advanced JSON edit) in the friendly form', () => { + const disabled = SniffingSchema.parse({ enabled: false }); + const enabled = SniffingSchema.parse({ enabled: true }); + const onChange = vi.fn(); + + const { rerender, getByRole } = render( + , + ); + expect(getByRole('switch').getAttribute('aria-checked')).toBe('false'); + + rerender(); + expect(getByRole('switch').getAttribute('aria-checked')).toBe('true'); + }); +});