Skip to content

Commit

Permalink
Fix token input for typing balance value manually (#862)
Browse files Browse the repository at this point in the history
Resolves #764

### What
When user was typing the balance amount manually then input was not
updating values correctly.
We moved to `useCallback` instead of `useEffect` and fixed the condition
for updating parent component with new values.

The issue was caused mostly by incorrect condition but I wanted to get
rid of `useEffect` as the dependencies array was intentionally
incomplete and it seems like it wasn't the most correct hook anyway.

### Testing

General regression testing is needed here (@michalinacienciala). Let's
not merge unless it will be tested for regressions.

- [x] make sure scenarios written in the task above are working
correctly now
- [x] test staking and unstaking both full and partial amounts
- [x] make sure we can stake/unstake values with decent precision
(either by typing or using "max" button)


![image](https://github.com/tahowallet/dapp/assets/20949277/c4756451-b6eb-425b-8641-fea353ed4f6d)
  • Loading branch information
michalinacienciala authored Dec 11, 2023
2 parents d96ff90 + 97f1a54 commit d57d1b4
Showing 1 changed file with 23 additions and 19 deletions.
42 changes: 23 additions & 19 deletions src/shared/components/Interface/TokenAmountInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,24 +76,28 @@ export default function TokenAmountInput({
[balance, onValidate]
)

useEffect(() => {
const textToBigIntAmount =
textAmount === "" ? null : userAmountToBigInt(textAmount) ?? 0n

const bigIntToTextAmount = bigIntToPreciseUserAmount(balance)

// As we may be loosing some precision, we need to compare the values.
// Clicking "Max" button may result in bigint that is too big to be
// represented as a float number. In this case we need to compare values to
// not override the external value that stores the bigint using greater precision.
if (textToBigIntAmount !== amount && textAmount !== bigIntToTextAmount) {
onChange(textToBigIntAmount)
}

// Make sure this is working only one way:
// from the text provided by input to the parent component
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [textAmount, onChange])
const internalOnChange = useCallback(
(newValue: string) => {
setTextAmount(newValue)

const newValueBigIntAmount =
newValue === "" ? null : userAmountToBigInt(newValue) ?? 0n

const balanceTextAmount = bigIntToPreciseUserAmount(balance)

// As we may be loosing some precision, we need to compare the values.
// Clicking "Max" button may result in bigint that is too big to be
// represented as a float number. In this case we need to compare values to
// not override the external value that stores the bigint using greater precision.
if (
newValueBigIntAmount !== amount &&
(newValue !== balanceTextAmount || newValueBigIntAmount === balance)
) {
onChange(newValueBigIntAmount)
}
},
[amount, balance, onChange]
)

useEffect(() => {
// Allow clearing the input from parent componentthis should be the only case
Expand All @@ -115,7 +119,7 @@ export default function TokenAmountInput({
label={inputLabel}
value={textAmount}
disabled={disabled}
onChange={setTextAmount}
onChange={internalOnChange}
validate={validate}
rightComponent={
<Button
Expand Down

0 comments on commit d57d1b4

Please sign in to comment.