Merge pull request 'правки' (#47) from table-optimization-fix into test
Reviewed-on: #47
This commit is contained in:
commit
18ec053e44
@ -23,7 +23,7 @@ const FORMULA_INDICATOR_STYLES = {
|
|||||||
|
|
||||||
const TEXTAREA_STYLES = {
|
const TEXTAREA_STYLES = {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: 'auto',
|
height: '3rem',
|
||||||
fieldSizing: 'content',
|
fieldSizing: 'content',
|
||||||
fontSize: 'inherit',
|
fontSize: 'inherit',
|
||||||
};
|
};
|
||||||
@ -32,7 +32,6 @@ const EditCell = memo(({ refCell, onChange, disabled, value, tableId, cellId, ta
|
|||||||
const { endEditing: contextEndEditing } = useRealtime();
|
const { endEditing: contextEndEditing } = useRealtime();
|
||||||
const storageKey = `formula_${tableId}_${cellId}`;
|
const storageKey = `formula_${tableId}_${cellId}`;
|
||||||
|
|
||||||
// Объединенное состояние
|
|
||||||
const [state, setState] = useState(() => ({
|
const [state, setState] = useState(() => ({
|
||||||
currentValue: value,
|
currentValue: value,
|
||||||
displayValue: value,
|
displayValue: value,
|
||||||
@ -40,7 +39,7 @@ const EditCell = memo(({ refCell, onChange, disabled, value, tableId, cellId, ta
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
// Позиция ячейки
|
// Позиция ячейки
|
||||||
const [position, setPosition] = useState({ left: 0, width: 0, translateY: '' });
|
const [position, setPosition] = useState();
|
||||||
const textareaRef = useRef(null);
|
const textareaRef = useRef(null);
|
||||||
|
|
||||||
const refFinished = useRef(false);
|
const refFinished = useRef(false);
|
||||||
@ -89,8 +88,8 @@ const EditCell = memo(({ refCell, onChange, disabled, value, tableId, cellId, ta
|
|||||||
if (!el) return;
|
if (!el) return;
|
||||||
|
|
||||||
const resize = () => {
|
const resize = () => {
|
||||||
el.style.height = 'auto';
|
|
||||||
el.style.minHeight = '3rem';
|
el.style.minHeight = '3rem';
|
||||||
|
el.style.height = '3rem';
|
||||||
el.style.height = el.scrollHeight + 'px';
|
el.style.height = el.scrollHeight + 'px';
|
||||||
el.style.maxHeight = '180px';
|
el.style.maxHeight = '180px';
|
||||||
};
|
};
|
||||||
@ -102,16 +101,6 @@ const EditCell = memo(({ refCell, onChange, disabled, value, tableId, cellId, ta
|
|||||||
return () => observer.disconnect();
|
return () => observer.disconnect();
|
||||||
}, [state.currentValue]);
|
}, [state.currentValue]);
|
||||||
|
|
||||||
// Фокус при монтировании
|
|
||||||
useEffect(() => {
|
|
||||||
const el = textareaRef.current;
|
|
||||||
if (el && !disabled) {
|
|
||||||
el.focus();
|
|
||||||
el.setSelectionRange(el.value.length, el.value.length);
|
|
||||||
}
|
|
||||||
}, [disabled]);
|
|
||||||
|
|
||||||
// Сохранение
|
|
||||||
const handleSave = useCallback(() => {
|
const handleSave = useCallback(() => {
|
||||||
const { currentValue } = state;
|
const { currentValue } = state;
|
||||||
|
|
||||||
@ -146,7 +135,6 @@ const EditCell = memo(({ refCell, onChange, disabled, value, tableId, cellId, ta
|
|||||||
}
|
}
|
||||||
}, [state, storageKey, onChange]);
|
}, [state, storageKey, onChange]);
|
||||||
|
|
||||||
// Завершение редактирования
|
|
||||||
const finishEditing = useCallback(() => {
|
const finishEditing = useCallback(() => {
|
||||||
if (refFinished.current) return;
|
if (refFinished.current) return;
|
||||||
refFinished.current = true;
|
refFinished.current = true;
|
||||||
@ -170,7 +158,6 @@ const EditCell = memo(({ refCell, onChange, disabled, value, tableId, cellId, ta
|
|||||||
return () => document.removeEventListener('mousedown', handleClickOutside);
|
return () => document.removeEventListener('mousedown', handleClickOutside);
|
||||||
}, [finishEditing]);
|
}, [finishEditing]);
|
||||||
|
|
||||||
// Обработчики событий
|
|
||||||
const handleChange = useCallback((e) => {
|
const handleChange = useCallback((e) => {
|
||||||
const value = e.target.value;
|
const value = e.target.value;
|
||||||
setState(prev => ({
|
setState(prev => ({
|
||||||
@ -187,12 +174,11 @@ const EditCell = memo(({ refCell, onChange, disabled, value, tableId, cellId, ta
|
|||||||
}
|
}
|
||||||
}, [finishEditing]);
|
}, [finishEditing]);
|
||||||
|
|
||||||
// Мемоизация стилей
|
|
||||||
const editorStyles = useMemo(() => ({
|
const editorStyles = useMemo(() => ({
|
||||||
...EDITOR_STYLES,
|
...EDITOR_STYLES,
|
||||||
left: position.left,
|
left: position?.left || 0,
|
||||||
width: position.width,
|
width: position?.width || 0,
|
||||||
transform: position.translateY,
|
transform: position?.translateY || 0,
|
||||||
}), [position]);
|
}), [position]);
|
||||||
|
|
||||||
const textareaStyles = useMemo(() => ({
|
const textareaStyles = useMemo(() => ({
|
||||||
@ -204,6 +190,7 @@ const EditCell = memo(({ refCell, onChange, disabled, value, tableId, cellId, ta
|
|||||||
return (
|
return (
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
{position &&
|
||||||
<div style={editorStyles}>
|
<div style={editorStyles}>
|
||||||
{state.isFormulaMode && (
|
{state.isFormulaMode && (
|
||||||
<div style={FORMULA_INDICATOR_STYLES}>fx</div>
|
<div style={FORMULA_INDICATOR_STYLES}>fx</div>
|
||||||
@ -218,6 +205,8 @@ const EditCell = memo(({ refCell, onChange, disabled, value, tableId, cellId, ta
|
|||||||
placeholder={state.isFormulaMode ? 'Введите формулу (начинается с =)' : ''}
|
placeholder={state.isFormulaMode ? 'Введите формулу (начинается с =)' : ''}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// components/RealtimeTable/index.js
|
|
||||||
import React, { useState, useMemo, useRef, useEffect, useCallback, useTransition } from 'react';
|
import React, { useState, useMemo, useRef, useEffect, useCallback, useTransition } from 'react';
|
||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
// getTableColumns.js
|
|
||||||
import React, { useEffect, useRef, useState, useMemo, useCallback } from 'react';
|
import React, { useEffect, useRef, useState, useMemo, useCallback } from 'react';
|
||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import { useParams } from 'react-router';
|
import { useParams } from 'react-router';
|
||||||
import { useRealtime } from './contexts/RealtimeContext';
|
import { useRealtime } from './contexts/RealtimeContext';
|
||||||
|
|
||||||
// Мемоизированный компонент EditCellPortal
|
|
||||||
const EditCellPortal = React.memo(({
|
const EditCellPortal = React.memo(({
|
||||||
cell,
|
cell,
|
||||||
table,
|
table,
|
||||||
@ -22,7 +20,6 @@ const EditCellPortal = React.memo(({
|
|||||||
|
|
||||||
const { endEditing: contextEndEditing } = useRealtime();
|
const { endEditing: contextEndEditing } = useRealtime();
|
||||||
|
|
||||||
// Оптимизация: вычисляем позицию только при монтировании и изменении cell
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (ref.current) {
|
if (ref.current) {
|
||||||
const tbodyRef = ref.current.offsetParent?.offsetParent?.offsetParent;
|
const tbodyRef = ref.current.offsetParent?.offsetParent?.offsetParent;
|
||||||
@ -30,9 +27,8 @@ const EditCellPortal = React.memo(({
|
|||||||
setRefTbody(tbodyRef);
|
setRefTbody(tbodyRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [refTbody]); // Добавляем refTbody в зависимости
|
}, []);
|
||||||
|
|
||||||
// Мемоизация обработчика изменения
|
|
||||||
const handleChange = useCallback( (val) => {
|
const handleChange = useCallback( (val) => {
|
||||||
table.setEditingCell(null);
|
table.setEditingCell(null);
|
||||||
try {
|
try {
|
||||||
@ -53,7 +49,6 @@ const EditCellPortal = React.memo(({
|
|||||||
}
|
}
|
||||||
}, [table, cell, onError]);
|
}, [table, cell, onError]);
|
||||||
|
|
||||||
// Мемоизация пропсов для EditCell
|
|
||||||
const editCellProps = useMemo(() => ({
|
const editCellProps = useMemo(() => ({
|
||||||
refCell: ref,
|
refCell: ref,
|
||||||
cell,
|
cell,
|
||||||
@ -65,7 +60,6 @@ const EditCellPortal = React.memo(({
|
|||||||
cellId: `${cell.row.id}_${cell.column.id}`,
|
cellId: `${cell.row.id}_${cell.column.id}`,
|
||||||
}), [cell, isEditable, handleChange, tableKey, table]);
|
}), [cell, isEditable, handleChange, tableKey, table]);
|
||||||
|
|
||||||
// Мемоизация портала
|
|
||||||
const portalContent = useMemo(() => {
|
const portalContent = useMemo(() => {
|
||||||
if (!refTbody || isSaving) return null;
|
if (!refTbody || isSaving) return null;
|
||||||
return createPortal(
|
return createPortal(
|
||||||
@ -82,9 +76,7 @@ const EditCellPortal = React.memo(({
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
EditCellPortal.displayName = 'EditCellPortal';
|
|
||||||
|
|
||||||
// Основная функция getTableColumns
|
|
||||||
export const getTableColumns = ({
|
export const getTableColumns = ({
|
||||||
Cell,
|
Cell,
|
||||||
EditCell,
|
EditCell,
|
||||||
@ -95,11 +87,9 @@ export const getTableColumns = ({
|
|||||||
const columnColors = { ...columnsConfig.colors };
|
const columnColors = { ...columnsConfig.colors };
|
||||||
const columns = structuredClone(columnsConfig.columns);
|
const columns = structuredClone(columnsConfig.columns);
|
||||||
|
|
||||||
// Кэши для вычисленных значений
|
|
||||||
const cellPropsCache = new WeakMap();
|
const cellPropsCache = new WeakMap();
|
||||||
const editPropsCache = new WeakMap();
|
const editPropsCache = new WeakMap();
|
||||||
|
|
||||||
// Функция для получения кешированных пропсов Cell
|
|
||||||
const getCachedCellProps = (row, column, table) => {
|
const getCachedCellProps = (row, column, table) => {
|
||||||
const key = `${row.id}_${column.id}`;
|
const key = `${row.id}_${column.id}`;
|
||||||
|
|
||||||
@ -109,7 +99,6 @@ export const getTableColumns = ({
|
|||||||
|
|
||||||
const rowCache = cellPropsCache.get(row);
|
const rowCache = cellPropsCache.get(row);
|
||||||
if (rowCache[key]) {
|
if (rowCache[key]) {
|
||||||
// Проверяем, не изменились ли фильтры
|
|
||||||
const cached = rowCache[key];
|
const cached = rowCache[key];
|
||||||
const currentGlobalFilter = table.getState().globalFilter;
|
const currentGlobalFilter = table.getState().globalFilter;
|
||||||
const currentColumnFilter = table.getState().columnFilters?.find(f => f.id === column.id)?.value;
|
const currentColumnFilter = table.getState().columnFilters?.find(f => f.id === column.id)?.value;
|
||||||
@ -136,7 +125,6 @@ export const getTableColumns = ({
|
|||||||
return props;
|
return props;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Функция для получения кешированных пропсов Edit
|
|
||||||
const getCachedEditProps = (row, column, table) => {
|
const getCachedEditProps = (row, column, table) => {
|
||||||
const key = `${row.id}_${column.id}`;
|
const key = `${row.id}_${column.id}`;
|
||||||
|
|
||||||
@ -160,11 +148,9 @@ export const getTableColumns = ({
|
|||||||
// Оптимизированная функция processColumns
|
// Оптимизированная функция processColumns
|
||||||
const processColumns = (columns) => {
|
const processColumns = (columns) => {
|
||||||
columns.forEach((col) => {
|
columns.forEach((col) => {
|
||||||
// Оптимизированный Cell
|
|
||||||
col.Cell = ({ cell, table, column, row }) => {
|
col.Cell = ({ cell, table, column, row }) => {
|
||||||
const props = getCachedCellProps(row, column, table);
|
const props = getCachedCellProps(row, column, table);
|
||||||
|
|
||||||
// Используем useMemo для мемоизации пропсов
|
|
||||||
const cellProps = useMemo(() => ({
|
const cellProps = useMemo(() => ({
|
||||||
row,
|
row,
|
||||||
column,
|
column,
|
||||||
@ -175,11 +161,9 @@ export const getTableColumns = ({
|
|||||||
return <Cell {...cellProps} />;
|
return <Cell {...cellProps} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Оптимизированный Edit
|
|
||||||
col.Edit = ({ cell, table, row, column }) => {
|
col.Edit = ({ cell, table, row, column }) => {
|
||||||
const props = getCachedEditProps(row, column, table);
|
const props = getCachedEditProps(row, column, table);
|
||||||
|
|
||||||
// Мемоизируем компонент EditCellPortal
|
|
||||||
const editComponent = useMemo(() => (
|
const editComponent = useMemo(() => (
|
||||||
<EditCellPortal
|
<EditCellPortal
|
||||||
cell={cell}
|
cell={cell}
|
||||||
@ -193,7 +177,6 @@ export const getTableColumns = ({
|
|||||||
return editComponent;
|
return editComponent;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Рекурсивно обрабатываем вложенные колонки
|
|
||||||
if (col.columns?.length) {
|
if (col.columns?.length) {
|
||||||
processColumns(col.columns);
|
processColumns(col.columns);
|
||||||
}
|
}
|
||||||
@ -202,7 +185,6 @@ export const getTableColumns = ({
|
|||||||
|
|
||||||
processColumns(columns);
|
processColumns(columns);
|
||||||
|
|
||||||
// Оптимизированная колонка с номерами строк
|
|
||||||
const rowNumber = {
|
const rowNumber = {
|
||||||
accessorKey: 'sort_order',
|
accessorKey: 'sort_order',
|
||||||
header: '#',
|
header: '#',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user