Skip to content

Commit

Permalink
feat: introduced useActions hook for max cleanliness
Browse files Browse the repository at this point in the history
  • Loading branch information
woodenfurniture committed Nov 12, 2024
1 parent 0b118ff commit 1bffd50
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 84 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { Divider, Stack } from '@chakra-ui/react'
import { skipToken } from '@reduxjs/toolkit/query'
import type { AccountId } from '@shapeshiftoss/caip'
import { fromAccountId } from '@shapeshiftoss/caip'
import { getDefaultSlippageDecimalPercentageForSwapper, SwapperName } from '@shapeshiftoss/swapper'
import type { Asset } from '@shapeshiftoss/types'
import { BigNumber, bn, bnOrZero, fromBaseUnit, toBaseUnit } from '@shapeshiftoss/utils'
import type { FormEvent } from 'react'
import { useCallback, useEffect, useMemo, useState } from 'react'
Expand All @@ -13,6 +11,7 @@ import type { Address } from 'viem'
import { WarningAcknowledgement } from 'components/Acknowledgement/Acknowledgement'
import { TradeInputTab } from 'components/MultiHopTrade/types'
import { WalletActions } from 'context/WalletProvider/actions'
import { useActions } from 'hooks/useActions'
import { useErrorHandler } from 'hooks/useErrorToast/useErrorToast'
import { useWallet } from 'hooks/useWallet/useWallet'
import { useQuoteLimitOrderQuery } from 'state/apis/limit-orders/limitOrderApi'
Expand Down Expand Up @@ -40,7 +39,7 @@ import {
selectIsTradeQuoteRequestAborted,
selectShouldShowTradeQuoteOrAwaitInput,
} from 'state/slices/tradeQuoteSlice/selectors'
import { useAppDispatch, useAppSelector } from 'state/store'
import { useAppSelector } from 'state/store'

import { SharedSlippagePopover } from '../../SharedTradeInput/SharedSlippagePopover'
import { SharedTradeInput } from '../../SharedTradeInput/SharedTradeInput'
Expand All @@ -67,7 +66,6 @@ export const LimitOrderInput = ({
dispatch: walletDispatch,
state: { isConnected, isDemoWallet },
} = useWallet()
const dispatch = useAppDispatch()

const history = useHistory()
const { handleSubmit } = useFormContext()
Expand All @@ -90,6 +88,18 @@ export const LimitOrderInput = ({
const isVotingPowerLoading = useAppSelector(selectIsVotingPowerLoading)
const userCurrencyRate = useAppSelector(selectUserCurrencyToUsdRate)

const {
switchAssets,
setSellAsset,
setBuyAsset,
setSellAssetAccountId,
setBuyAssetAccountId,
setLimitPriceBuyAsset,
setSlippagePreferencePercentage,
setIsInputtingFiatSellAmount,
setSellAmountCryptoPrecision,
} = useActions(limitOrderInput.actions)

const feeParams = useMemo(
() => ({ feeModel: 'SWAPPER' as const, inputAmountUsd: inputSellAmountUsd }),
[inputSellAmountUsd],
Expand Down Expand Up @@ -127,24 +137,6 @@ export const LimitOrderInput = ({
return ''
}, [])

const handleSwitchAssets = useCallback(() => {
dispatch(limitOrderInput.actions.switchAssets())
}, [dispatch])

const handleSetSellAsset = useCallback(
(newSellAsset: Asset) => {
dispatch(limitOrderInput.actions.setSellAsset(newSellAsset))
},
[dispatch],
)

const handleSetBuyAsset = useCallback(
(newBuyAsset: Asset) => {
dispatch(limitOrderInput.actions.setBuyAsset(newBuyAsset))
},
[dispatch],
)

const handleConnect = useCallback(() => {
walletDispatch({ type: WalletActions.SET_WALLET_MODAL, payload: true })
}, [walletDispatch])
Expand Down Expand Up @@ -180,20 +172,6 @@ export const LimitOrderInput = ({
[handleFormSubmit],
)

const handleSetSellAccountId = useCallback(
(newSellAccountId: AccountId) => {
dispatch(limitOrderInput.actions.setSellAssetAccountId(newSellAccountId))
},
[dispatch],
)

const handleSetBuyAccountId = useCallback(
(newBuyAccountId: AccountId) => {
dispatch(limitOrderInput.actions.setBuyAssetAccountId(newBuyAccountId))
},
[dispatch],
)

const sellAmountCryptoBaseUnit = useMemo(() => {
return toBaseUnit(sellAmountCryptoPrecision, sellAsset.precision)
}, [sellAmountCryptoPrecision, sellAsset.precision])
Expand Down Expand Up @@ -254,15 +232,8 @@ export const LimitOrderInput = ({
// TODO: If we introduce polling of quotes, we will need to add logic inside `LimitOrderConfig` to
// not reset the user's config unless the asset pair changes.
useEffect(() => {
dispatch(limitOrderInput.actions.setLimitPriceBuyAsset(marketPriceBuyAsset))
}, [dispatch, marketPriceBuyAsset])

const handleSetLimitPriceBuyAsset = useCallback(
(newMarketPriceBuyAsset: string) => {
dispatch(limitOrderInput.actions.setLimitPriceBuyAsset(newMarketPriceBuyAsset))
},
[dispatch],
)
setLimitPriceBuyAsset(marketPriceBuyAsset)
}, [setLimitPriceBuyAsset, marketPriceBuyAsset])

const isLoading = useMemo(() => {
return (
Expand All @@ -285,37 +256,16 @@ export const LimitOrderInput = ({
shouldShowTradeQuoteOrAwaitInput,
])

const handleSetUserSlippagePercentage = useCallback(
(slippagePercentage: string | undefined) => {
dispatch(limitOrderInput.actions.setSlippagePreferencePercentage(slippagePercentage))
},
[dispatch],
)

const handleSetIsInputtingFiatSellAmount = useCallback(
(isInputtingFiatSellAmount: boolean) => {
dispatch(limitOrderInput.actions.setIsInputtingFiatSellAmount(isInputtingFiatSellAmount))
},
[dispatch],
)

const handleSetSellAmountCryptoPrecision = useCallback(
(sellAmountCryptoPrecision: string) => {
dispatch(limitOrderInput.actions.setSellAmountCryptoPrecision(sellAmountCryptoPrecision))
},
[dispatch],
)

const headerRightContent = useMemo(() => {
return (
<SharedSlippagePopover
defaultSlippagePercentage={defaultSlippagePercentage}
quoteSlippagePercentage={undefined} // No slippage returned by CoW
userSlippagePercentage={userSlippagePercentage}
setUserSlippagePercentage={handleSetUserSlippagePercentage}
setUserSlippagePercentage={setSlippagePreferencePercentage}
/>
)
}, [defaultSlippagePercentage, handleSetUserSlippagePercentage, userSlippagePercentage])
}, [defaultSlippagePercentage, setSlippagePreferencePercentage, userSlippagePercentage])

const bodyContent = useMemo(() => {
return (
Expand All @@ -327,19 +277,19 @@ export const LimitOrderInput = ({
sellAmountUserCurrency={inputSellAmountUserCurrency}
sellAsset={sellAsset}
sellAccountId={sellAccountId}
handleSwitchAssets={handleSwitchAssets}
onChangeIsInputtingFiatSellAmount={handleSetIsInputtingFiatSellAmount}
onChangeSellAmountCryptoPrecision={handleSetSellAmountCryptoPrecision}
setSellAsset={handleSetSellAsset}
setSellAccountId={handleSetSellAccountId}
handleSwitchAssets={switchAssets}
onChangeIsInputtingFiatSellAmount={setIsInputtingFiatSellAmount}
onChangeSellAmountCryptoPrecision={setSellAmountCryptoPrecision}
setSellAsset={setSellAsset}
setSellAccountId={setSellAssetAccountId}
>
<Stack>
<LimitOrderBuyAsset
asset={buyAsset}
accountId={buyAccountId}
isInputtingFiatSellAmount={isInputtingFiatSellAmount}
onAccountIdChange={handleSetBuyAccountId}
onSetBuyAsset={handleSetBuyAsset}
onAccountIdChange={setBuyAssetAccountId}
onSetBuyAsset={setBuyAsset}
/>
<Divider />
<LimitOrderConfig
Expand All @@ -348,7 +298,7 @@ export const LimitOrderInput = ({
isLoading={isLoading}
marketPriceBuyAsset={marketPriceBuyAsset}
limitPriceBuyAsset={limitPriceBuyAsset}
setLimitPriceBuyAsset={handleSetLimitPriceBuyAsset}
setLimitPriceBuyAsset={setLimitPriceBuyAsset}
/>
</Stack>
</SharedTradeInputBody>
Expand All @@ -364,14 +314,14 @@ export const LimitOrderInput = ({
sellAccountId,
sellAmountCryptoPrecision,
sellAsset,
handleSetIsInputtingFiatSellAmount,
handleSetBuyAccountId,
handleSetBuyAsset,
handleSetLimitPriceBuyAsset,
handleSetSellAccountId,
handleSetSellAmountCryptoPrecision,
handleSetSellAsset,
handleSwitchAssets,
setBuyAsset,
setBuyAssetAccountId,
setIsInputtingFiatSellAmount,
setLimitPriceBuyAsset,
setSellAmountCryptoPrecision,
setSellAsset,
setSellAssetAccountId,
switchAssets,
])

const affiliateFeeAfterDiscountUserCurrency = useMemo(() => {
Expand Down
20 changes: 20 additions & 0 deletions src/hooks/useActions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { ActionCreatorsMapObject } from '@reduxjs/toolkit'
import { bindActionCreators } from '@reduxjs/toolkit'
import { useMemo } from 'react'
import { useDispatch } from 'react-redux'

// A hook that binds Redux action creators to dispatch, allowing them to be called directly without
// manually calling `dispatch` and memoizing with `useCallback`. Returns an object with the same
// shape as the input actions, but with each action creator wrapped to automatically dispatch its
// action.
export function useActions<T extends ActionCreatorsMapObject>(
actions: T,
): {
[P in keyof T]: T[P] extends (...args: any[]) => any
? (...args: Parameters<T[P]>) => ReturnType<T[P]>
: T[P]
} {
const dispatch = useDispatch()

return useMemo(() => bindActionCreators(actions, dispatch), [actions, dispatch])
}

0 comments on commit 1bffd50

Please sign in to comment.