diff --git a/app/src/sandbox/project/ProjectDemo.tsx b/app/src/sandbox/project/ProjectDemo.tsx index 058319b4b9..56c236369d 100644 --- a/app/src/sandbox/project/ProjectDemo.tsx +++ b/app/src/sandbox/project/ProjectDemo.tsx @@ -32,7 +32,7 @@ let savedValue: FormState = { items: getDemoTasks() }; export function ProjectDemo() { const { - lens, value, onValueChange, save, isChanged, revert, undo, canUndo, redo, canRedo, + lens, value, save, isChanged, revert, undo, canUndo, redo, canRedo, setValue, } = useForm({ value: savedValue, onSave: async (data) => { @@ -57,26 +57,33 @@ export function ProjectDemo() { task.parentId = tempRelativeTask.parentId; } - task.order = getInsertionOrder( - Object.values(value.items) - .filter((i) => i.parentId === task.parentId) - .map((i) => i.order), - position === 'bottom' || position === 'inside' ? 'after' : 'before', // 'inside' drop should also insert at the top of the list, so it's ok to default to 'before' - tempRelativeTask?.order, - ); + setValue((currentValue) => { + task.order = getInsertionOrder( + Object.values(currentValue.items) + .filter((i) => i.parentId === task.parentId) + .map((i) => i.order), + position === 'bottom' || position === 'inside' ? 'after' : 'before', // 'inside' drop should also insert at the top of the list, so it's ok to default to 'before' + tempRelativeTask?.order, + ); + + return { ...currentValue, items: { ...currentValue.items, [task.id]: task } }; + }); - onValueChange({ ...value, items: { ...value.items, [task.id]: task } }); if (position === 'inside') { - setTableState({ ...tableState, folded: { ...tableState.folded, [`${task.parentId}`]: false } }); + setTableState((currentTableState) => ({ + ...currentTableState, + folded: { ...currentTableState.folded, [`${task.parentId}`]: false }, + })); } - }, [value, onValueChange, tableState, setTableState]); + }, [setValue, setTableState]); const deleteTask = useCallback((task: Task) => { - const items = { ...value.items }; - - delete items[task.id]; - onValueChange({ ...value, items }); - }, [value, onValueChange]); + setValue((currentValue) => { + const items = { ...currentValue.items }; + delete items[task.id]; + return { ...currentValue, items }; + }); + }, [setValue]); const handleCanAcceptDrop = useCallback((params: AcceptDropParams) => { if (!params.srcData.isTask || params.srcData.id === params.dstData.id) { diff --git a/uui-core/src/data/processing/hooks/types.ts b/uui-core/src/data/processing/hooks/types.ts index 08e6aedbc6..fd873602d5 100644 --- a/uui-core/src/data/processing/hooks/types.ts +++ b/uui-core/src/data/processing/hooks/types.ts @@ -39,3 +39,9 @@ ListState & { */ loadData?: boolean; }; + +export type UseListOptionsProps> = { + view: IView; + listState: DataSourceState; + props: TProps; +}; diff --git a/uui-core/src/data/processing/hooks/useList.ts b/uui-core/src/data/processing/hooks/useList.ts index d29df1d961..0628452f7a 100644 --- a/uui-core/src/data/processing/hooks/useList.ts +++ b/uui-core/src/data/processing/hooks/useList.ts @@ -1,14 +1,28 @@ import { useEffect, useMemo, useRef } from 'react'; import { useView } from './useView'; -import { UnboxListProps, UseListProps } from './types'; +import { ListViewProps, UnboxListProps, UseListOptionsProps, UseListProps } from './types'; import { createView, mergePropsWithDefaults } from './helpers'; +function useListOptions>({ + view, listState, props, +}: UseListOptionsProps) { + const deps: unknown[] = [view, listState]; + if (props.type === 'array') { + deps.push( + Array.isArray(props.items) + ? props.items.length + : props.items, + ); + } + + return useMemo(() => view.getListProps(), deps); +} + export function useList( { listState, setListState, loadData = true, ...props }: UseListProps, deps: any[], ) { const prevLoadDataRef = useRef(false); - // const prevListState = usePrevious(listState); useEffect(() => { prevLoadDataRef.current = loadData; @@ -29,8 +43,7 @@ export function useList( } const rows = view.getVisibleRows(); - const listProps = useMemo(() => view.getListProps(), [view, listState]); - + const listProps = useListOptions({ view, props, listState }); return { rows, listProps,