Commit ce6c7831 authored by Zach Pomerantz's avatar Zach Pomerantz Committed by GitHub

fix: trade UI latency (#3563)

* fix: do not delay trade update

* fix: do not delay initial input
parent 64e8c3ce
import styled, { css } from 'lib/theme'
import { forwardRef, HTMLProps, useCallback, useEffect, useState } from 'react'
import { forwardRef, HTMLProps, useCallback } from 'react'
const Input = styled.input`
-webkit-appearance: textfield;
......@@ -76,46 +76,23 @@ interface EnforcedNumericInputProps extends NumericInputProps {
enforcer: (nextUserInput: string) => string | null
}
function isNumericallyEqual(a: string, b: string) {
const [aInteger, aDecimal] = toParts(a)
const [bInteger, bDecimal] = toParts(b)
return aInteger === bInteger && aDecimal === bDecimal
function toParts(num: string) {
let [integer, decimal] = num.split('.')
integer = integer?.match(/([1-9]\d*)/)?.[1] || ''
decimal = decimal?.match(/(\d*[1-9])/)?.[1] || ''
return [integer, decimal]
}
}
const NumericInput = forwardRef<HTMLInputElement, EnforcedNumericInputProps>(function NumericInput(
{ value, onChange, enforcer, pattern, ...props }: EnforcedNumericInputProps,
ref
) {
const [state, setState] = useState(value ?? '')
useEffect(() => {
if (!isNumericallyEqual(state, value)) {
setState(value ?? '')
}
}, [value, state, setState])
const validateChange = useCallback(
(event) => {
const nextInput = enforcer(event.target.value.replace(/,/g, '.'))
if (nextInput !== null) {
setState(nextInput ?? '')
if (!isNumericallyEqual(nextInput, value)) {
onChange(nextInput)
}
onChange(nextInput)
}
},
[value, onChange, enforcer]
[onChange, enforcer]
)
return (
<Input
value={state}
value={value}
onChange={validateChange}
// universal input options
inputMode="decimal"
......
......@@ -95,20 +95,17 @@ export default function useClientSideSmartOrderRouterTrade<TTradeType extends Tr
[currencyIn, currencyOut, quoteResult, tradeType]
)
const gasUseEstimateUSD = useStablecoinAmountFromFiatValue(quoteResult?.gasUseEstimateUSD) ?? null
const trade =
useLast(
useMemo(() => {
if (route) {
try {
return route && transformRoutesToTrade(route, tradeType, gasUseEstimateUSD)
} catch (e: unknown) {
console.debug('transformRoutesToTrade failed: ', e)
}
}
return
}, [gasUseEstimateUSD, route, tradeType]),
Boolean
) ?? undefined
const trade = useMemo(() => {
if (route) {
try {
return route && transformRoutesToTrade(route, tradeType, gasUseEstimateUSD)
} catch (e: unknown) {
console.debug('transformRoutesToTrade failed: ', e)
}
}
return
}, [gasUseEstimateUSD, route, tradeType])
const lastTrade = useLast(trade, Boolean) ?? undefined
// Dont return old trade if currencies dont match.
const isStale =
......@@ -125,9 +122,9 @@ export default function useClientSideSmartOrderRouterTrade<TTradeType extends Tr
if (isStale) {
return { state: TradeState.LOADING, trade: undefined }
} else if (isDebouncing) {
return { state: TradeState.SYNCING, trade }
return { state: TradeState.SYNCING, trade: lastTrade }
} else if (isLoading) {
return { state: TradeState.LOADING, trade }
return { state: TradeState.LOADING, trade: lastTrade }
}
}
......@@ -154,14 +151,15 @@ export default function useClientSideSmartOrderRouterTrade<TTradeType extends Tr
}, [
currencyIn,
currencyOut,
error,
quoteResult,
error,
route,
queryArgs,
trade,
isStale,
isDebouncing,
isLoading,
lastTrade,
tradeType,
])
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment