Memoizing Components

The memo parameter on @ui.component optimizes component rendering by skipping re-renders when a component’s props haven’t changed. This is similar to React.memo and is useful for improving performance in components that render often with the same props.

Note

The memo parameter is for memoizing entire components. To memoize a value or computation within a component, use the use_memo hook instead.

Basic Usage

Add memo=True to your component to skip re-renders when props are unchanged:

In this example, clicking the button increments count, causing app to re-render. However, greeting will not re-render because its prop ("World") hasn’t changed.

How It Works

When a parent component re-renders, its children are considered for re-rendering too. With memo=True, deephaven.ui compares the new props with the previous props using shallow equality. If all props are equal, the component skips rendering and reuses its previous result.

Memoization only applies to props from the parent. A memoized component will still re-render when its own state changes.

The render cycle with memoization:

  1. Trigger: Parent component state changes
  2. Render: Parent re-renders, but memoized children with unchanged props are skipped
  3. Commit: Only changed parts of the UI are updated

When to Use memo

Treat memo as a performance optimization, not as a requirement for correctness. Most components do not need it. Keep in mind that memoization itself has overhead—comparing props on every render takes time, so it only helps when the cost of skipping a re-render is greater than the cost of the comparison.

Use memo=True when:

  • A component re-renders often with the same props
  • A component is expensive to render because it builds a large UI subtree or many children
  • A parent component re-renders frequently but passes stable props to the child
  • You have measured or observed lag from unnecessary re-renders

Don’t use memo when:

  • The component’s props change on almost every render
  • The component is cheap to render
  • The expensive part is a calculation inside the component. Use use_memo for that instead.
  • The underlying issue is an impure render or side effect during rendering
  • You’re prematurely optimizing without measuring performance

In this example, use_memo keeps entries stable, while memo=True avoids rebuilding the activity_feed subtree each time dashboard updates for unrelated reasons.

Syntax Options

The memo parameter accepts different values:

Custom Comparison Function

By default, memo=True uses shallow equality to compare props. You can provide a custom comparison function by passing it directly to memo:

Warning

Custom comparison functions are rarely necessary. Prefer reducing prop changes first by passing simpler props or stabilizing objects and callbacks with use_memo and use_callback. If you do write a custom comparator, compare every prop that affects rendering or behavior.

The custom comparison function receives two dictionaries:

  • prev_props: The props from the previous render
  • next_props: The props for the current render

Return True to skip re-rendering (props are “equal”), or False to re-render.

When writing a custom comparison function:

  • Compare every prop, including callback props
  • Only use custom comparison for data with a known, limited shape
  • Measure whether the comparison is actually cheaper than re-rendering
  • Avoid generic deep equality checks on unknown or deeply nested structures

Common Pitfalls

Creating New Objects in Props

When you pass a new object, list, or dictionary as a prop, it will always be a different reference, causing re-renders even if the content is the same:

Passing Callback Functions

Lambda functions and inline function definitions create new references each render:

Side Effects During Rendering

Memoized components still need pure rendering logic. If a component mutates global state, performs I/O, or depends on side effects during rendering, memo can hide the bug by causing that render to run less often.

Keep rendering pure, and move side effects into event handlers or use_effect.

Comparison with use_memo

Featurememo parameteruse_memo
PurposeSkip re-rendering a componentCache a computed value
UsageParameter on @ui.componentHook inside component
InputComponent propsDependencies array
OutputMemoized componentMemoized value

Use memo=True on @ui.component to optimize component rendering. Use use_memo to optimize expensive calculations within a component.