From fb8114792a9803f987d45bfb6e12e7eec82e2425 Mon Sep 17 00:00:00 2001 From: Wood Date: Thu, 25 Sep 2025 22:43:26 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20sync=20FileUploader=20context=20with=20p?= =?UTF-8?q?rops=20to=20fix=20inconsistent=20file=20parameter=20state=20in?= =?UTF-8?q?=20=E2=80=9CView=20cached=20variables=E2=80=9D.=20(#26199)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/base/file-uploader/store.tsx | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/web/app/components/base/file-uploader/store.tsx b/web/app/components/base/file-uploader/store.tsx index cddfdf6f27..7f7cfd5693 100644 --- a/web/app/components/base/file-uploader/store.tsx +++ b/web/app/components/base/file-uploader/store.tsx @@ -1,6 +1,7 @@ import { createContext, useContext, + useEffect, useRef, } from 'react' import { @@ -18,13 +19,11 @@ type Shape = { export const createFileStore = ( value: FileEntity[] = [], - onChange?: (files: FileEntity[]) => void, ) => { return create(set => ({ files: value ? [...value] : [], setFiles: (files) => { set({ files }) - onChange?.(files) }, })) } @@ -55,9 +54,35 @@ export const FileContextProvider = ({ onChange, }: FileProviderProps) => { const storeRef = useRef(undefined) + const onChangeRef = useRef(onChange) + const isSyncingRef = useRef(false) if (!storeRef.current) - storeRef.current = createFileStore(value, onChange) + storeRef.current = createFileStore(value) + + // keep latest onChange + useEffect(() => { + onChangeRef.current = onChange + }, [onChange]) + + // subscribe to store changes and call latest onChange + useEffect(() => { + const store = storeRef.current! + const unsubscribe = store.subscribe((state: Shape) => { + if (isSyncingRef.current) return + onChangeRef.current?.(state.files) + }) + return unsubscribe + }, []) + + // sync external value into internal store when value changes + useEffect(() => { + const store = storeRef.current! + const nextFiles = value ? [...value] : [] + isSyncingRef.current = true + store.setState({ files: nextFiles }) + isSyncingRef.current = false + }, [value]) return (