Реагируйте useCallback с параметром - PullRequest
3 голосов
/ 16 апреля 2020

Использование перехватчика useCallback в React - это просто оболочка вокруг useMemo, специально предназначенная для функций, чтобы избежать постоянного создания новых экземпляров функций в рамках компонентов. Мой вопрос возникает, когда вам нужно передать аргумент в обратный вызов, созданный из памятки.

Например, обратный вызов, созданный так ...

const Button: React.FunctionComponent = props => {
    const onClick = React.useCallback(() => alert('Clicked!'), [])
    return <button onClick={onClick}>{props.children}</button>
}

- простой пример запомненный обратный вызов и не требующий передачи внешних значений в него для выполнения sh своей работы. Тем не менее, если я хочу создать шаблонный обратный вызов c для типа функции React.Dipatch<React.SetStateAction>, тогда потребуются аргументы ... например:

const Button: React.FunctionComponent = props => {
    const [loading, setLoading] = React.useState(false)
    const genericSetLoadingCb = React.useCallback((x: boolean) => () => setLoading(x), [])

    return <button onClick={genericSetLoadingCb(!loading)}>{props.children}</button>
}

В моей голове это выглядит как точно так же, как делать следующее ...

const Button: React.FunctionComponent = props => {
    const [loading, setLoading] = React.useState(false)
    return <button onClick={() => setLoading(!loading)}>{props.children}</button>
}

, что позволило бы победить цель запоминания функции, потому что она все равно будет создавать новую функцию при каждом рендеринге, поскольку genericSetLoadingCb(false) будет просто возвращать новая функция также для каждого рендера.

Правильно ли это понимание или шаблон, описанный с аргументами, все еще сохраняет преимущества запоминания?

1 Ответ

2 голосов
/ 16 апреля 2020
const genericSetLoadingCb = React.useCallback((x: boolean) => () => setLoading(x), [])

То, что вы сделали выше, это убедитесь, что genericSetLoadingCb остается неизменным при повторных рендерах Однако каждый раз, когда вы создаете из нее новую функцию , например:

genericSetLoadingCb(!loading)

Возвращаемая функция будет отличаться при каждом рендеринге . Чтобы гарантировать, что возвращаемая функция запомнена, вам нужно что-то вроде этого:

 let memoizedcb = React.useCallback(
    memoize((x: boolean) => () => setLoading(x)),
    []
  );

Я использую быстрое запоминание, например

import memoize from "fast-memoize";

Простое использование памятки не будет работать, как при следующем рендере, он вызовет памятку из fre sh следующим образом:

let memoized = memoize(fn)

memoized('foo', 3, 'bar')
memoized('foo', 3, 'bar') // cache hit

memoized = memoize(fn); // without useCallback this would happen on next render 

// Now the previous cache is lost
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...