20

Is there any way to set new generic in React.memo?

For example, for class components, I can use

// set generic
class GenericClass<G extends string | number> extends PureComponent {}

// and use like this
<GenericClass<number> />

In the below scenario, I want to make type G generic.

type G = string;
const MemoComponent = memo<{ value: G; onValueChange: (newValue: G) => void }>(
  ({ value, onValueChange }) => {
    return (
      <select
        onClick={() => {
          // do calculation
          onValueChange(value);
        }}
      >
        Button
      </button>
    );
  }
);

I want to know is there any way to set generic in React.memo too? For example, like below

const MemoComponent = <G extends string | number | object>React.memo<{value: G}>(({value}) => component)

// and use like this
<MemoComponent<number> />
Thu San
  • 1,400
  • 1
  • 17
  • 29
  • Can you add more code? Show what you have tried? What is the final thing you expect out of the memoized component? – Mukesh Soni Aug 13 '19 at 12:11
  • Related: https://stackoverflow.com/questions/60386614/how-to-use-props-with-generics-with-react-memo/60389122#60389122 – ford04 Mar 29 '21 at 09:35

3 Answers3

71

I had the same issue and solved like this.

    interface ISomeComponentWithGenericsProps<T> { value: T; } 

    function SomeComponentWithGenerics<T>(props: ISomeComponentWithGenericsProps<T>) {
      return <span>{props.value}</span>;
    }

    export default React.memo(SomeComponentWithGenerics) as typeof SomeComponentWithGenerics;

Rafael Fontes
  • 1,195
  • 11
  • 19
25

You can write your own wrapper not to use type assertion(as) :

const genericMemo: <T>(component: T) => T = memo

function GenericComponent<Value>({props: PropsWithGeneric<Value>}) {
  return <div />
}

export const GenericMemoComponent = genericMemo(GenericComponent)
0

Expanding on Dmitriy Vergiles' answer - to include the propsAreEqual equality function:

const genericMemo: <T>(
  component: T,
  propsAreEqual?: (
    prevProps: React.PropsWithChildren<T>,
    nextProps: React.PropsWithChildren<T>
  ) => boolean
) => T = memo;

function GenericComponent<Value>({props: PropsWithGeneric<Value>}) {
  return <div />
}

export const GenericMemoComponent = genericMemo(
  GenericComponent, 
  (prevProps, nextProps) => {
    // Check props
  }
)

Turnip
  • 352
  • 4
  • 7