Skip to content

Optimize Meta and DimSelectors #680

Description

@TheJeran

Problem

The performance for the Metadim selectors is still really poor. The reason is all of the unstable props passed to children components.

Example

Pressing an increment should only re-render two components.


Image

But we can see it re-renders everything.

Image Image

All of that is from one state change. And that is happening every single time you drag the slider.

The issue

The issue is all of highlighted lines will re-render this component

 <DimSlicer
                key={row.id}
                availableDims={availableDims}
                dimName={row.dimName}
                onDimChange={(name) => updateDimName(row.id, name)}  < --- This
                onRemove={isLast && rows.length > 1 ? removeLastRow : undefined} < --- This
                dimSize={dim?.size ?? 0}
                selection={row.sel}
                axis={row.axis}
                onChange={(sel) => updateSel(row.id, sel)}   < --- This
                values={dim?.values}
                formatValue={dim?.formatValue}
                lockMode="slice"
                allowedAxes={['z', 'y', 'x']}  < --- This
              />

This is because each re-render of the parent re-runs all unstabilized code. So the lambda function () -> are all new each render which triggers a re-render of the entire child component.

Image

Unfortunately I cannot figure out why tf the main component renders. It unhelpfully just says hook 37 changed.

Image

Fix

All of these need to be stabilized. So the arrow functions need to use useCallback

const removeLastRow = useCallback(() =>
    setRows((prev) => {
      const newRows = prev.slice(0, -1);
      const defaultAxes: Axis[] = ['z', 'y', 'x'];
      const axes = defaultAxes.slice(-newRows.length);
      return newRows.map((r, i) => ({ ...r, axis: axes[i] }));
    }),[setRows]) ;

With that callback now we see onRemove no longer triggers a rerender

Image

allowedAxes isn't even used in the child component. So these also could use a cleaning pass.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions