0

I'm trying to recreate the effect shown at https://hexed.it/

When you hover over either list the corresponding byte in the other list is also highlighted. I figured a panel with each list inside it that had a state with the current hovered byte would do but it seems that React wants to re-render the entire list or do something strange every time resulting in larger files being unbearably slow.

I see a lot of "use memo! use the useCallback hook!" when searching and I've tried... it's still slow and I'm not sure why. It seems like it's only rendering the updated HexByte but it's still unacceptably slow for large files.

Sandbox: https://codesandbox.io/s/flamboyant-ellis-btfk5s

Can someone help me quicken/smooth out the hovering?

bluewave41
  • 135
  • 2
  • 13
  • 1
    Maybe better to make a code sanbox instead of trying to get someone to go download your whole github repo just to help you out. – super Jul 09 '22 at 21:14

1 Answers1

0

I solved it using this answer: Prevent DOM element re-render in virtualized tree component using react-window

In short the things I've learned:

  • memo has no effect if a component has a useState in it
  • Large lists of data should be rendered using a library like react-window
  • The cell rendering function as mentioned in the answer above can't be part of a parent component

As an example for anyone coming here, the new HexPanel class looks like so

import Box from '@mui/material/Box';
import { memo } from 'react';
import { FixedSizeGrid as Grid, areEqual } from 'react-window';

const HexByte = memo(function HexByte(props) {
    const onMouseEnter = () => {
        props.onHover(props.index);
        //setInside(true);
    }
    const onMouseLeave = () => {
        //setInside(false);
    }
    const onClick = () => {
        //setClicked(true);
    }

    return (
        <span
            style={{
                display: 'inline-block',
                padding: '5px',
                backgroundColor: props.hoverIndex == props.index ? '#777' : 'transparent',
                color: 'darkblue'
            }}
            onClick={onClick}
            onMouseEnter={onMouseEnter}
            onMouseLeave={onMouseLeave}
        >
            {props.byte}
        </span>
    )
}, (prevProps, nextProps) => nextProps.hoverIndex != nextProps.index);

const Cell = memo(function({ data, columnIndex, rowIndex, style }) {
    return (
        <div style={style}>
            <HexByte byte={data.hex[rowIndex][columnIndex]} onHover={data.onHover} hoverIndex={data.hoverIndex} index={`${rowIndex}${columnIndex}`} />
        </div>
    )
}, areEqual);

const HexPanel = (props) => {
    return (
        <Box
            sx={{
                fontFamily: 'Source Code Pro',
                display: 'flex',
                flexDirection: 'column',
            }}
        >
            <Grid
                columnCount={16}
                columnWidth={30}
                height={900}
                itemData={props}
                rowCount={props.hex.length}
                rowHeight={35}
                width={500}
            >
                {Cell}
            </Grid>
        </Box>
    )
}

export default HexPanel;
bluewave41
  • 135
  • 2
  • 13