From d743f787e9d77efc2e080708e393ad6016f9d6c7 Mon Sep 17 00:00:00 2001 From: Arjun Porwal <65214523+ap211unitech@users.noreply.github.com> Date: Mon, 12 May 2025 22:11:51 +0530 Subject: [PATCH] Refactor: Vote component (#11540) * refactor: simplify Vote component by removing local state * refactor: improve comment clarity in Vote component's useMemo logic --- packages/react-params/src/Param/Vote.tsx | 64 +++++++++++++----------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/packages/react-params/src/Param/Vote.tsx b/packages/react-params/src/Param/Vote.tsx index d93b8b9618..aa7b1d3f6e 100644 --- a/packages/react-params/src/Param/Vote.tsx +++ b/packages/react-params/src/Param/Vote.tsx @@ -3,7 +3,7 @@ import type { Props } from '../types.js'; -import React, { useCallback, useEffect, useRef, useState } from 'react'; +import React, { useCallback, useMemo, useRef } from 'react'; import { Dropdown } from '@polkadot/react-components'; import { GenericVote } from '@polkadot/types'; @@ -12,30 +12,49 @@ import { isBn, isNumber } from '@polkadot/util'; import { useTranslation } from '../translate.js'; import Bare from './Bare.js'; -interface VoteParts { - aye: boolean; - conviction: number; -} - const AYE_MASK = 0b10000000; -const EMPTY_VOTE: VoteParts = { aye: true, conviction: 0 }; +// In this approach, it will avoid using additional local states and instead rely directly on the parent-provided values and methods. function Vote ({ className = '', defaultValue: { value }, isDisabled, isError, onChange, withLabel }: Props): React.ReactElement { const { t } = useTranslation(); - const [vote, setVote] = useState(EMPTY_VOTE); - useEffect((): void => { - onChange && onChange({ isValid: true, value: vote }); - }, [onChange, vote]); + // Derive aye and conviction from the value prop + const { aye, conviction } = useMemo(() => { + // Logic sucks here, but to be honest, can not find other way to do it + const resolvedAye = value instanceof GenericVote + ? value.isAye + : isBn(value) + ? !!(value.toNumber() & AYE_MASK) + : isNumber(value) + ? !!(value & AYE_MASK) + : typeof value === 'object' && value !== null && 'aye' in value + ? !!value.aye + : true; + + const resolvedConviction = value instanceof GenericVote + ? value.conviction.index + : typeof value === 'object' && value !== null && 'conviction' in value + ? Number(value.conviction) + : 0; + + return { + aye: resolvedAye, + conviction: resolvedConviction + }; + }, [value]); const onChangeVote = useCallback( - (aye: boolean) => setVote(({ conviction }) => ({ aye, conviction })), - [] + (newAye: boolean) => { + onChange?.({ isValid: true, value: { aye: newAye, conviction } }); + }, + [conviction, onChange] ); const onChangeConviction = useCallback( - (conviction: number) => setVote(({ aye }) => ({ aye, conviction })), - [] + (newConviction: number) => { + onChange?.({ isValid: true, value: { aye, conviction: newConviction } }); + }, + [aye, onChange] ); const optAyeRef = useRef([ @@ -53,22 +72,11 @@ function Vote ({ className = '', defaultValue: { value }, isDisabled, isError, o { text: t('Locked6x'), value: 6 } ]); - const defaultVote = isBn(value) - ? !!(value.toNumber() & AYE_MASK) - : isNumber(value) - ? !!(value & AYE_MASK) - : value instanceof GenericVote - ? value.isAye - : !!value; - const defaultConv = value instanceof GenericVote - ? value.conviction.index - : 0; - return (