'TransferList is so slow

I made faster TextField and Select referring to below.

TextField Unnecessary Re-renders

But even though I used useMemo TransferList could make faster just a little.
My current code is here:

import Grid from "@mui/material/Grid";
import List from "@mui/material/List";
import ListItem from "@mui/material/ListItem";
import ListItemIcon from "@mui/material/ListItemIcon";
import ListItemText from "@mui/material/ListItemText";
import Checkbox from "@mui/material/Checkbox";
import Button from "@mui/material/Button";
import Paper from "@mui/material/Paper";
import React, { useMemo } from "react";

interface TransferListProps {
  items: any;
  setData: (value: any) => void;
}

interface Props {
  customList: any;
  right: any[];
  left: any[];
  handleAllRight: any;
  handleCheckedRight: any;
  leftChecked: any;
  handleCheckedLeft: any;
  rightChecked: any;
  handleAllLeft: any;
}

function not(a: readonly number[], b: readonly number[]) {
  console.log(a.filter((value) => b.indexOf(value) === -1));
  return a.filter((value) => b.indexOf(value) === -1);
}

function intersection(a: readonly number[], b: readonly number[]) {
  return a.filter((value) => b.indexOf(value) !== -1);
}

const TransferListComponent = React.memo((props: Props) => {
  return (
    <Grid container spacing={2} justifyContent="start" alignItems="center">
      <Grid item>{props.customList(props.left)}</Grid>
      <Grid item>
        <Grid container direction="column" alignItems="center">
          <Button
            sx={{ my: 0.5 }}
            variant="outlined"
            size="small"
            onClick={props.handleAllRight}
            disabled={props.left.length === 0}
            aria-label="move all right"
          >
            ≫
          </Button>
          <Button
            sx={{ my: 0.5 }}
            variant="outlined"
            size="small"
            onClick={props.handleCheckedRight}
            disabled={props.leftChecked.length === 0}
            aria-label="move selected right"
          >
            &gt;
          </Button>
          <Button
            sx={{ my: 0.5 }}
            variant="outlined"
            size="small"
            onClick={props.handleCheckedLeft}
            disabled={props.rightChecked.length === 0}
            aria-label="move selected left"
          >
            &lt;
          </Button>
          <Button
            sx={{ my: 0.5 }}
            variant="outlined"
            size="small"
            onClick={props.handleAllLeft}
            disabled={props.right.length === 0}
            aria-label="move all left"
          >
            ≪
          </Button>
        </Grid>
      </Grid>
      <Grid item>{props.customList(props.right)}</Grid>
    </Grid>
  );
});

export default function TransferList(props: TransferListProps) {
  const [checked, setChecked] = React.useState<readonly any[]>([]);
  const [left, setLeft] = React.useState<any[]>(
    props.items.map((value: any) => {
      return value.name;
    })
  );
  const [right, setRight] = React.useState<any[]>([]);

  const leftChecked = intersection(checked, left);
  const rightChecked = intersection(checked, right);

  const handleToggle = useMemo(
    () => (value: number) => () => {
      const currentIndex = checked.indexOf(value);
      const newChecked = [...checked];
      if (currentIndex === -1) {
        newChecked.push(value);
      } else {
        newChecked.splice(currentIndex, 1);
      }
      setChecked(newChecked);
    },
    [rightChecked]
  );

  const handleAllRight = useMemo(
    () => () => {
      setRight(right.concat(left));
      props.setData(right.concat(left));
      setLeft([]);
    },
    [rightChecked]
  );

  const handleCheckedRight = useMemo(
    () => () => {
      setRight(right.concat(leftChecked));
      props.setData(right.concat(leftChecked));
      setLeft(not(left, leftChecked));
      setChecked(not(checked, leftChecked));
    },
    [rightChecked]
  );

  const handleCheckedLeft = useMemo(
    () => () => {
      setLeft(left.concat(rightChecked));
      setRight(not(right, rightChecked));
      props.setData(not(right, rightChecked));
      setChecked(not(checked, rightChecked));
    },
    [rightChecked]
  );

  const handleAllLeft = useMemo(
    () => () => {
      setLeft(left.concat(right));
      setRight([]);
      props.setData([]);
    },
    [rightChecked]
  );

  const customList = useMemo(
    () => (items: string[]) =>
      (
        <Paper sx={{ width: 175, height: 230, overflow: "auto" }}>
          <List dense component="div" role="list">
            {items.map((value: any) => {
              const labelId = `transfer-list-item-${value}-label`;
              const randomNumber = Math.random();

              return (
                <ListItem
                  key={randomNumber}
                  role="listitem"
                  button
                  onClick={handleToggle(value)}
                >
                  <ListItemIcon>
                    <Checkbox
                      checked={checked.indexOf(value) !== -1}
                      tabIndex={-1}
                      disableRipple
                      inputProps={{
                        "aria-labelledby": labelId,
                      }}
                    />
                  </ListItemIcon>
                  <ListItemText id={labelId} primary={`${value}`} />
                </ListItem>
              );
            })}
            <ListItem />
          </List>
        </Paper>
      ),
    [rightChecked]
  );

  return (
    <TransferListComponent
      customList={customList}
      left={left}
      right={right}
      handleAllRight={handleAllRight}
      handleCheckedRight={handleCheckedRight}
      leftChecked={leftChecked}
      handleCheckedLeft={handleCheckedLeft}
      rightChecked={rightChecked}
      handleAllLeft={handleAllLeft}
    />
  );
}

This is the relation to describe parent and child.

UsersSearchTransferListTransferListComponent

Could you give me advise?
Thank you.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source