Digamos que eu tenho 3 entradas: rate, sendAmount e receiveAmount. Coloquei essas 3 entradas nos parâmetros diferentes useEffect. As regras são:
- Se sendAmount for alterado, eu calculo
receiveAmount = sendAmount * rate
- Se receiveAmount mudou, eu calculo
sendAmount = receiveAmount / rate
- Se a taxa for alterada, calculo
receiveAmount = sendAmount * rate
quandosendAmount > 0
ou calculosendAmount = receiveAmount / rate
quandoreceiveAmount > 0
Aqui está a codesandbox https://codesandbox.io/s/pkl6vn7x6j para demonstrar o problema.
Existe uma maneira de comparar o oldValues
e newValues
como em componentDidUpdate
vez de fazer 3 manipuladores para este caso?
obrigado
Aqui está minha solução final com usePrevious
https://codesandbox.io/s/30n01w2r06
Nesse caso, não posso usar vários useEffect
porque cada alteração está levando à mesma chamada de rede. É por isso que eu também uso changeCount
para acompanhar a mudança. Isso changeCount
também é útil para rastrear alterações somente do local, para que eu possa impedir chamadas de rede desnecessárias devido a alterações do servidor.
fonte
Respostas:
Você pode escrever um gancho personalizado para fornecer adereços anteriores usando useRef
e depois use-o
useEffect
No entanto, é mais claro e provavelmente melhor e mais claro de ler e entender se você usar dois
useEffect
separadamente para cada ID de mudança, deseja processá-los separadamentefonte
useEffect
chamadas separadamente. Não sabia que você poderia usá-lo várias vezes!useEffect
dependências que estão faltandoprevAmount
Caso alguém esteja procurando uma versão de uso do TypeScript
fonte
const usePrevious = <T extends any>(...
fazer o intérprete veja pensar que <T> não é JSX e é uma restrição genérica<T extends {}>
que não vai funcionar. Parece estar funcionando para mim, mas estou tentando entender a complexidade de usá-lo dessa maneira..tsx
Os arquivos contêm jsx, que deve ser idêntico ao html. É possível que o genérico<T>
seja uma tag de componente não fechada.Missing return type on function.eslint(@typescript-eslint/explicit-function-return-type)
Opção 1 - useCompare hook
Comparar um valor atual a um valor anterior é um padrão comum e justifica um gancho personalizado próprio que oculta os detalhes da implementação.
Demo
Opção 2 - execute useEffect quando o valor for alterado
Demo
fonte
Acabei de publicar react-delta, que resolve esse tipo exato de cenário. Na minha opinião,
useEffect
tem muitas responsabilidades.Responsabilidades
Object.is
Quebrando responsabilidades
react-delta
divideuseEffect
as responsabilidades em vários ganchos menores.Responsabilidade # 1
usePrevious(value)
useLatest(value)
useDelta(value, options)
useDeltaArray(valueArray, options)
useDeltaObject(valueObject, options)
some(deltaArray)
every(deltaArray)
Responsabilidade # 2
useConditionalEffect(callback, boolean)
Na minha experiência, essa abordagem é mais flexível, limpa e concisa do que
useEffect
/useRef
solutions.fonte
Como o estado não está fortemente associado à instância do componente nos componentes funcionais, o estado anterior não pode ser alcançado
useEffect
sem salvá-lo primeiro, por exemplo, comuseRef
. Isso também significa que a atualização do estado possivelmente foi implementada incorretamente no lugar errado, porque o estado anterior está disponível nasetState
função atualizador.Este é um bom caso de uso para o
useReducer
qual fornece armazenamento semelhante ao Redux e permite implementar o respectivo padrão. As atualizações de estado são executadas explicitamente, portanto, não há necessidade de descobrir qual propriedade de estado é atualizada; isso já está claro na ação despachada.Aqui está um exemplo de como pode ser:
fonte
sendAmount
, etc, de forma assíncrona, em vez de calculá-las, certo? Isso muda muito. É possível fazer isso com,useReduce
mas pode ser complicado. Se você lidou com o Redux antes de saber que as operações assíncronas não são simples lá. O github.com/reduxjs/redux-thunk é uma extensão popular do Redux que permite ações assíncronas. Aqui está uma demonstração que aumenta useReducer com o mesmo padrão (useThunkReducer), codesandbox.io/s/6z4r79ymwr . Observe que a função despachada éasync
, você pode fazer solicitações lá (comentadas).O uso de Ref introduzirá um novo tipo de bug no aplicativo.
Vamos ver este caso usando
usePrevious
alguém que comentou antes:Como podemos ver aqui, não estamos atualizando o interno
ref
porque estamos usandouseEffect
fonte
state
... e não oprops
... quando você se preocupa com os adereços antigos, o erro ocorre.Para uma comparação realmente simples de objetos propostos, você pode usar o useEffect para verificar facilmente se um objeto foi atualizado.
useEffect executará seu código somente se o suporte for alterado.
fonte
prop
alterações consecutivas, você não poderá mais~ do stuff here ~
setHasPropChanged(false)
no final de~ do stuff here ~
"redefinir" seu estado. (Mas isso iria repor em uma renderizados adicional)Saindo da resposta aceita, uma solução alternativa que não requer um gancho personalizado:
fonte
useRef
nãouserRef
. Esqueci de usar a correnteprevAmount.current
Aqui está um gancho personalizado que eu acredito que é mais intuitivo do que usar
usePrevious
.Você usaria da
useTransition
seguinte maneira.Espero que ajude.
fonte