Frontend — Code Quality
Summary
Every time the contract polling cycle completes, the entire proposal list re-renders even when individual proposal data has not changed. This issue reduces wasted renders by memoizing the two most frequently rendered components and the derived proposal arrays that feed them.
Background
ProposalCard.tsx and ApprovalBar.tsx are plain function components with no memoization. In App.tsx, the activeProposals and historyProposals arrays are derived inline from the proposals state on every render, creating new array references each time even when the underlying data is identical. The onApprove and onExecute callbacks passed to ProposalCard are also recreated each render because they are defined as arrow functions inline in App.tsx.
What Needs to Be Done
- In
frontend/src/components/ProposalCard.tsx, wrap the component export with React.memo so it only re-renders when its own props change.
- In
frontend/src/components/ApprovalBar.tsx, wrap the component export with React.memo for the same reason.
- In
frontend/src/App.tsx, replace the inline activeProposals and historyProposals array derivations with useMemo calls that depend only on the proposals array, so the derived arrays keep a stable reference between renders when proposals have not changed.
- In
frontend/src/App.tsx, wrap the handleApprove and handleExecute callback functions with useCallback so their references stay stable between renders and do not defeat the memoization added in steps 1 and 2.
Acceptance Criteria
Files to Look At
frontend/src/components/ProposalCard.tsx — wrap with React.memo
frontend/src/components/ApprovalBar.tsx — wrap with React.memo
frontend/src/App.tsx — add useMemo for derived arrays and useCallback for handlers
Difficulty: Medium
Frontend — Code Quality
Summary
Every time the contract polling cycle completes, the entire proposal list re-renders even when individual proposal data has not changed. This issue reduces wasted renders by memoizing the two most frequently rendered components and the derived proposal arrays that feed them.
Background
ProposalCard.tsxandApprovalBar.tsxare plain function components with no memoization. InApp.tsx, theactiveProposalsandhistoryProposalsarrays are derived inline from theproposalsstate on every render, creating new array references each time even when the underlying data is identical. TheonApproveandonExecutecallbacks passed toProposalCardare also recreated each render because they are defined as arrow functions inline inApp.tsx.What Needs to Be Done
frontend/src/components/ProposalCard.tsx, wrap the component export withReact.memoso it only re-renders when its own props change.frontend/src/components/ApprovalBar.tsx, wrap the component export withReact.memofor the same reason.frontend/src/App.tsx, replace the inlineactiveProposalsandhistoryProposalsarray derivations withuseMemocalls that depend only on theproposalsarray, so the derived arrays keep a stable reference between renders when proposals have not changed.frontend/src/App.tsx, wrap thehandleApproveandhandleExecutecallback functions withuseCallbackso their references stay stable between renders and do not defeat the memoization added in steps 1 and 2.Acceptance Criteria
ProposalCardis wrapped withReact.memo.ApprovalBaris wrapped withReact.memo.activeProposalsandhistoryProposalsinApp.tsxare derived withuseMemo.handleApproveandhandleExecuteinApp.tsxare wrapped withuseCallback.Files to Look At
frontend/src/components/ProposalCard.tsx— wrap withReact.memofrontend/src/components/ApprovalBar.tsx— wrap withReact.memofrontend/src/App.tsx— adduseMemofor derived arrays anduseCallbackfor handlersDifficulty: Medium