Dependências vazias com useMemo ou useCallback VS useRef

9

Nesta edição do GitHub, propus essencialmente mudar:

x = useCallback( ... , []);

Para:

x = useRef( ... ).current;

Os dois são iguais, mas com useRefReact não compara as dependências.

Para o qual uma resposta veio com uma pergunta:

Existe alguma situação em que useMemo ou useCallback sem dependência seja uma escolha melhor que useRef?

Não consigo pensar em um, mas posso ter esquecido alguns casos de uso.

Então, alguém pode pensar em tal situação?

Izhaki
fonte

Respostas:

5

Documentação da API Per React Hooks:

Lembre-se de que o useRef não o notifica quando o conteúdo é alterado. A mutação da propriedade .current não causa uma nova renderização ... O uso de uma ref de retorno de chamada garante que, mesmo que um componente filho exiba o nó medido posteriormente (por exemplo, em resposta a um clique), ainda seremos notificados no pai. componente e pode atualizar as medições.

Você pode ler mais sobre isso aqui e aqui .

irasuna
fonte
Acho que isso responde à pergunta, mas suspeito que isso esteja incorreto. No exemplo React da sandbox, alterar useCallback(x,[])para useRef(x)funciona da mesma maneira.
Izhaki
useRef(x).currentisso é.
Izhaki
Espero que eu esteja errado, mas eu fiz um caso por que os documentos estão errados: github.com/reactjs/reactjs.org/issues/2570
Izhaki
Não estou inteiramente certo sobre useCallback(cb, [])vs useRef(cb).currentmim. Embora useMemo(cb, [])seja diferente useRef(cb).currentno sentido em que useMemo"apenas recalculará o valor memorizado quando uma das dependências for alterada". Versus useRefque sempre recalcula o valor, não importa o quê.
irasuna
useRefnunca recalcula - sempre retorna o valor inicial.
Izhaki
1

Embora você possa usar useRef para emular useCallback ou com uma dependência vazia, você não pode usá-lo para todos os cenários possíveis de useCallback, que devem ser rememoizados quando qualquer uma das dependências mudar.

Além disso, não fará muita diferença de desempenho se você usar useCallback with empty dependencyou usar o Ref, pois ele não precisa realizar nenhuma comparação pesada.

Além disso, se você alterar um pouco a implementação da função para recriá-la em uma alteração de parâmetro específica, basta atualizar a implementação useCallbacke adicionar os parâmetros extras como dependência. No entanto, se você implementá-lo com useRef, precisará reverter parauseCallback

Shubham Khatri
fonte
11
Obrigado. Como o título sugere, este é um caso de dependências estritamente vazio.
Izhaki
11
@ Izhaki, eu entendo que sua pergunta é dependências estritamente vazias e é por isso que mencionei que não há diferença em caso de dependência vazia. Mas a sua quando você tenta adicionar mais mudanças, você pode precisar de um pouco de refatorar
Shubham Khatri
0

Como a saída da corrente useRef (() => {...}). É mutável.

O que pode causar efeitos colaterais estranhos no seu código. Eu posso alterar o valor da corrente a qualquer momento. https://codesandbox.io/s/confident-monad-vjeuw

Esse seria o caso de uso para não querer usar useRef

Daniel Duong
fonte
11
Mas x = useRef(value).currentnunca retorna instâncias mutáveis ​​- refnunca é retornado; currenté. É o mesmo que com a useCallbackversão.
Izhaki 18/11/19