Digamos que tengo 3 entradas: rate, sendAmount y recibenAmount. Puse esas 3 entradas en useEffect diffing params. Las reglas son:
- Si sendAmount cambió, calculo
receiveAmount = sendAmount * rate
- Si recibo Monto cambiado, calculo
sendAmount = receiveAmount / rate
- Si la tasa cambió, calculo
receiveAmount = sendAmount * rate
cuándosendAmount > 0
o calculosendAmount = receiveAmount / rate
cuándoreceiveAmount > 0
Aquí está el codesandbox https://codesandbox.io/s/pkl6vn7x6j para demostrar el problema.
¿Hay alguna manera de comparar el oldValues
y me newValues
gusta en componentDidUpdate
lugar de hacer 3 controladores para este caso?
Gracias
Aquí está mi solución final con usePrevious
https://codesandbox.io/s/30n01w2r06
En este caso, no puedo usar múltiples useEffect
porque cada cambio conduce a la misma llamada de red. Es por eso que también uso changeCount
para rastrear el cambio también. Esto changeCount
también es útil para realizar un seguimiento de los cambios solo locales, por lo que puedo evitar llamadas de red innecesarias debido a los cambios del servidor.
fuente
Respuestas:
Puede escribir un gancho personalizado para proporcionarle accesorios anteriores usando useRef
y luego usarlo en
useEffect
Sin embargo, es más claro y probablemente mejor y más claro de leer y comprender si usa dos
useEffect
por separado para cada ID de cambio que desea procesarlos por separadofuente
useEffect
llamadas por separado. ¡No sabía que podía usarlo varias veces!useEffect
faltan dependenciasprevAmount
En caso de que alguien esté buscando una versión de uso TypeScript Anterior:
fuente
const usePrevious = <T extends any>(...
hacer que el intérprete vea que <T> no es JSX y es una restricción genérica<T extends {}>
no funcionará? Parece estar funcionando para mí, pero estoy tratando de entender la complejidad de usarlo así..tsx
los archivos contienen jsx, que debe ser idéntico a html. Es posible que el genérico<T>
sea una etiqueta de componente no cerrada.Missing return type on function.eslint(@typescript-eslint/explicit-function-return-type)
Opción 1 - useComparar gancho
La comparación de un valor actual con un valor anterior es un patrón común, y justifica un enlace personalizado propio que oculta los detalles de la implementación.
Manifestación
Opción 2: ejecute useEffect cuando cambie el valor
Manifestación
fuente
Acabo de publicar react-delta que resuelve este tipo exacto de escenario. En mi opinión,
useEffect
tiene demasiadas responsabilidades.Responsabilidades
Object.is
Rompiendo responsabilidades
react-delta
rompeuseEffect
las responsabilidades en varios ganchos más pequeños.Responsabilidad # 1
usePrevious(value)
useLatest(value)
useDelta(value, options)
useDeltaArray(valueArray, options)
useDeltaObject(valueObject, options)
some(deltaArray)
every(deltaArray)
Responsabilidad # 2
useConditionalEffect(callback, boolean)
En mi experiencia, este enfoque es más flexible, limpio y conciso que
useEffect
/useRef
soluciones.fuente
Dado que el estado no está estrechamente acoplado con la instancia de componente en componentes funcionales, no se puede alcanzar el estado anterior
useEffect
sin guardarlo primero, por ejemplo, conuseRef
. Esto también significa que la actualización de estado posiblemente se implementó incorrectamente en un lugar incorrecto porque el estado anterior está disponible dentro de lasetState
función de actualización.Este es un buen caso de uso para el
useReducer
cual proporciona una tienda similar a Redux y permite implementar el patrón respectivo. Las actualizaciones de estado se realizan explícitamente, por lo que no es necesario averiguar qué propiedad de estado se actualiza; Esto ya está claro en la acción enviada.Aquí hay un ejemplo de cómo se vería:
fuente
sendAmount
, etc. de forma asincrónica en lugar de calcularlos, ¿verdad? Esto cambia mucho. Es posible hacer esto con,useReduce
pero puede ser complicado. Si trató con Redux antes, puede saber que las operaciones asíncronas no son sencillas allí. github.com/reduxjs/redux-thunk es una extensión popular para Redux que permite acciones asíncronas. Aquí hay una demostración que aumenta useReducer con el mismo patrón (useThunkReducer), codesandbox.io/s/6z4r79ymwr . Tenga en cuenta que la función despachada esasync
, puede hacer solicitudes allí (comentado).El uso de Ref introducirá un nuevo tipo de error en la aplicación.
Veamos este caso usando lo
usePrevious
que alguien comentó antes:Como podemos ver aquí, no estamos actualizando el interno
ref
porque estamos usandouseEffect
fuente
state
... y no elprops
... cuando te preocupas por los accesorios viejos, entonces se producirá un error.Para una comparación de accesorios realmente simple, puede usar useEffect para verificar fácilmente si un accesorio se ha actualizado.
useEffect solo ejecutará su código si el accesorio cambia.
fuente
prop
cambios consecutivos no podrás~ do stuff here ~
setHasPropChanged(false)
al final de~ do stuff here ~
"restablecer" su estado. (Pero esto sería restablecer en un reRender adicional)Saliendo de la respuesta aceptada, una solución alternativa que no requiere un enlace personalizado:
fuente
useRef
nouserRef
. Olvidé usar currentprevAmount.current
Aquí hay un gancho personalizado que uso que creo que es más intuitivo que usar
usePrevious
.Lo usarías de la
useTransition
siguiente manera.Espero que ayude.
fuente