mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Use react.memo for table rows
Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>
This commit is contained in:
parent
692c2ab88c
commit
ec66744ca3
@ -9,8 +9,8 @@ import React, { ReactNode } from "react";
|
||||
import { computed, makeObservable } from "mobx";
|
||||
import { Observer, observer } from "mobx-react";
|
||||
import { ConfirmDialog, ConfirmDialogParams } from "../confirm-dialog";
|
||||
import { Table, TableCell, TableCellProps, TableHead, TableProps, TableRow, TableRowProps, TableSortCallbacks } from "../table";
|
||||
import { boundMethod, cssNames, IClassName, isReactNode, prevDefault, stopPropagation } from "../../utils";
|
||||
import { Table, TableCell, TableCellProps, TableHead, TableProps, TableRowProps, TableSortCallbacks } from "../table";
|
||||
import { boundMethod, cssNames, IClassName, prevDefault, stopPropagation } from "../../utils";
|
||||
import { AddRemoveButtons, AddRemoveButtonsProps } from "../add-remove-buttons";
|
||||
import { NoItems } from "../no-items";
|
||||
import { Spinner } from "../spinner";
|
||||
@ -21,6 +21,7 @@ import { MenuActions } from "../menu/menu-actions";
|
||||
import { MenuItem } from "../menu";
|
||||
import { Checkbox } from "../checkbox";
|
||||
import { UserStore } from "../../../common/user-store";
|
||||
import { Row } from "./row";
|
||||
|
||||
export interface ItemListLayoutContentProps<I extends ItemObject> {
|
||||
getFilters: () => Filter[];
|
||||
@ -75,66 +76,43 @@ export class ItemListLayoutContent<I extends ItemObject> extends React.Component
|
||||
|
||||
getTableRow(item: I) {
|
||||
const {
|
||||
isSelectable, renderTableHeader, renderTableContents, renderItemMenu,
|
||||
renderTableHeader, renderTableContents, renderItemMenu,
|
||||
store, hasDetailsView, onDetails,
|
||||
copyClassNameFromHeadCells, customizeTableRowProps, detailsItem,
|
||||
customizeTableRowProps, detailsItem, isSelectable,
|
||||
} = this.props;
|
||||
const { isSelected } = store;
|
||||
const selected = detailsItem && detailsItem.getId() === item.getId();
|
||||
const onCheckboxChange = isSelectable ? prevDefault(() => store.toggleSelection(item)) : null;
|
||||
const itemMenu = renderItemMenu && (
|
||||
<TableCell className="menu">
|
||||
<div onClick={stopPropagation}>
|
||||
{renderItemMenu(item, store)}
|
||||
</div>
|
||||
</TableCell>
|
||||
);
|
||||
|
||||
return (
|
||||
<TableRow
|
||||
nowrap
|
||||
searchItem={item}
|
||||
sortItem={item}
|
||||
selected={detailsItem && detailsItem.getId() === item.getId()}
|
||||
<Row
|
||||
selected={selected}
|
||||
checked={isSelected(item)}
|
||||
renderTableHeader={renderTableHeader}
|
||||
cells={renderTableContents}
|
||||
itemMenu={itemMenu}
|
||||
onCheckboxChange={onCheckboxChange}
|
||||
onClick={hasDetailsView ? prevDefault(() => onDetails(item)) : undefined}
|
||||
item={item}
|
||||
showColumn={this.showColumn}
|
||||
{...customizeTableRowProps(item)}
|
||||
>
|
||||
{isSelectable && (
|
||||
<TableCell
|
||||
checkbox
|
||||
isChecked={isSelected(item)}
|
||||
onClick={prevDefault(() => store.toggleSelection(item))}
|
||||
/>
|
||||
)}
|
||||
{renderTableContents(item).map((content, index) => {
|
||||
const cellProps: TableCellProps = isReactNode(content)
|
||||
? { children: content }
|
||||
: content;
|
||||
const headCell = renderTableHeader?.[index];
|
||||
|
||||
if (copyClassNameFromHeadCells && headCell) {
|
||||
cellProps.className = cssNames(
|
||||
cellProps.className,
|
||||
headCell.className,
|
||||
);
|
||||
}
|
||||
|
||||
if (!headCell || this.showColumn(headCell)) {
|
||||
return <TableCell key={index} {...cellProps} />;
|
||||
}
|
||||
|
||||
return null;
|
||||
})}
|
||||
{renderItemMenu && (
|
||||
<TableCell className="menu">
|
||||
<div onClick={stopPropagation}>
|
||||
{renderItemMenu(item, store)}
|
||||
</div>
|
||||
</TableCell>
|
||||
)}
|
||||
</TableRow>
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
getRow(uid: string) {
|
||||
getRow(uid: string, item: I) {
|
||||
return (
|
||||
<div key={uid}>
|
||||
<Observer>
|
||||
{() => {
|
||||
const item = this.props.getItems().find(item => item.getId() === uid);
|
||||
|
||||
if (!item) return null;
|
||||
|
||||
return this.getTableRow(item);
|
||||
@ -202,7 +180,7 @@ export class ItemListLayoutContent<I extends ItemObject> extends React.Component
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.props.getItems().map(item => this.getRow(item.getId()));
|
||||
return this.props.getItems().map(item => this.getRow(item.getId(), item));
|
||||
}
|
||||
|
||||
renderTableHeader() {
|
||||
@ -285,11 +263,11 @@ export class ItemListLayoutContent<I extends ItemObject> extends React.Component
|
||||
);
|
||||
}
|
||||
|
||||
showColumn({ id: columnId, showWithColumn }: TableCellProps): boolean {
|
||||
showColumn = ({ id: columnId, showWithColumn }: TableCellProps): boolean => {
|
||||
const { tableId, isConfigurable } = this.props;
|
||||
|
||||
return !isConfigurable || !UserStore.getInstance().isTableColumnHidden(tableId, columnId, showWithColumn);
|
||||
}
|
||||
};
|
||||
|
||||
renderColumnVisibilityMenu() {
|
||||
const { renderTableHeader, tableId } = this.props;
|
||||
|
||||
69
src/renderer/components/item-object-list/row.tsx
Normal file
69
src/renderer/components/item-object-list/row.tsx
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import React, { memo, ReactNode } from "react";
|
||||
|
||||
import { cssNames, isReactNode } from "../../utils";
|
||||
import { TableCell, TableCellProps, TableRow } from "../table";
|
||||
|
||||
import type { ItemObject } from "../../../common/item.store";
|
||||
|
||||
interface RowProps<I extends ItemObject> {
|
||||
selected: boolean;
|
||||
checked?: boolean;
|
||||
renderTableHeader?: TableCellProps[];
|
||||
cells: (item: I) => (ReactNode | TableCellProps)[];
|
||||
itemMenu?: ReactNode;
|
||||
onCheckboxChange?: (evt: any) => void;
|
||||
onClick?: (evt: React.MouseEvent) => void;
|
||||
item: I;
|
||||
showColumn?: ({ id: columnId, showWithColumn }: TableCellProps) => boolean;
|
||||
}
|
||||
|
||||
export const Row = memo(<I extends ItemObject>({
|
||||
selected,
|
||||
checked,
|
||||
renderTableHeader,
|
||||
cells,
|
||||
itemMenu,
|
||||
onCheckboxChange,
|
||||
onClick,
|
||||
item,
|
||||
showColumn,
|
||||
...rest
|
||||
}: RowProps<I>) => {
|
||||
return (
|
||||
<TableRow
|
||||
nowrap
|
||||
searchItem={item}
|
||||
sortItem={item}
|
||||
selected={selected}
|
||||
onClick={onClick}
|
||||
{...rest}
|
||||
>
|
||||
{onCheckboxChange && (
|
||||
<TableCell
|
||||
checkbox
|
||||
isChecked={checked}
|
||||
onClick={onCheckboxChange}
|
||||
/>
|
||||
)}
|
||||
{cells(item).map((content, index) => {
|
||||
const cellProps: TableCellProps = isReactNode(content) ? { children: content } : content;
|
||||
const headCell = renderTableHeader?.[index];
|
||||
|
||||
if (headCell) {
|
||||
cellProps.className = cssNames(cellProps.className, headCell.className);
|
||||
}
|
||||
|
||||
if (!headCell || showColumn(headCell)) {
|
||||
return <TableCell key={index} {...cellProps} />;
|
||||
}
|
||||
|
||||
return null;
|
||||
})}
|
||||
{itemMenu}
|
||||
</TableRow>
|
||||
);
|
||||
});
|
||||
@ -67,7 +67,7 @@ export interface TableProps<Item> extends React.DOMAttributes<HTMLDivElement> {
|
||||
*/
|
||||
rowLineHeight?: number;
|
||||
customRowHeights?: (item: Item, lineHeight: number, paddings: number) => number;
|
||||
getTableRow?: (uid: string) => React.ReactElement<TableRowProps>;
|
||||
getTableRow?: (uid: string, item?: Item) => React.ReactElement<TableRowProps>;
|
||||
renderRow?: (item: Item) => React.ReactElement<TableRowProps>;
|
||||
}
|
||||
|
||||
|
||||
@ -134,7 +134,7 @@ export class VirtualList extends Component<VirtualListProps, State> {
|
||||
|
||||
interface RowData {
|
||||
items: ItemObject[];
|
||||
getRow?: (uid: string | number) => React.ReactElement<TableRowProps>;
|
||||
getRow?: (uid: string | number, item?: ItemObject) => React.ReactElement<TableRowProps>;
|
||||
}
|
||||
|
||||
export interface RowProps extends ListChildComponentProps {
|
||||
@ -146,7 +146,7 @@ const Row = observer((props: RowProps) => {
|
||||
const { items, getRow } = data;
|
||||
const item = items[index];
|
||||
const uid = typeof item == "string" ? index : items[index].getId();
|
||||
const row = getRow(uid);
|
||||
const row = getRow(uid, item);
|
||||
|
||||
if (!row) return null;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user