Home > front end >  Passing memoized function down into React Component as a prop causes Typescript error which I can�
Passing memoized function down into React Component as a prop causes Typescript error which I can�

Time:06-23

I have a component that has some props defined like this. The prop in this case is a function that allows us to pass data up into the parent or calling function

type compProps = {
    liftableData: (data: IData[] | undefined | false) => void
}
export const BasicComponent = (props: compProps) => {
    const { liftableData } = props

    // .... more code here 

    return <div>Some output</div>
}

Then when I use BasicComponent like this

const [someState, setSomeState] = useState<string>('')

const memodData = useMemo((liftableData: IData[] | undefined | false)  => {
  setSomeState(liftableData)
}, [])

<BasicComponent liftableData={memodData} />

But typescript gives me this error and I have tried all sorts to fix it with no success

Type 'void' is not assignable to type '(liftableData: false | IData[] | undefined) => void'.

How do I setup the memoized function to pass down as a prop ?How do I get rid of the error ?

CodePudding user response:

That's because useMemo is used for variables. memodData will be the result of the useMemo handler you passed: here (liftableData: IData[] | undefined | false) => { setSomeState(liftableData) } doesn't return anything => memodData is void

You should instead use useCallback to got a function:

const memodData = useCallback((liftableData: IData[] | undefined | false)  => {
  setSomeState(liftableData)
}, [])

CodePudding user response:

Let's take a look on useMemo type signature:

function useMemo<T>(factory: () => T, deps: DependencyList | undefined): T

First argument of useMemo is expected to be a function without arguments whereas you are trying to provide a function with arguments.

See this example:

let foo = () => { }
let bar = (arg: number) => { 
    arg.toExponential()
}

foo = bar // error, fn with args is not assignable to fn without args
bar = foo

const withCallback = (fn: () => void) => { }

withCallback(bar) // expected error

Why do you have this error ? Imagine that there is no error when you are trying to assign bar to foo.

let foo = () => { }
let bar = (arg: number) => {
    arg.toExponential()
}
// @ts-ignore
foo = bar 
foo()

You have a runtime error because it is unsafe operation.

Lets go back to your example, in order to provide some arguments to useMemo, you should provide them as a second argument of useMemo like here:

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

Please see docs

  • Related