77
88import React from "react" ;
99import equals from "deep-equal" ;
10- import { pathOr } from "../../utils/utils" ;
1110import "rc-slider/assets/index.css" ;
1211
1312type TaskIdExamples = Record < string , string > ;
@@ -16,7 +15,7 @@ type TaskIdFilterValues = Record<string, string>;
1615
1716interface TaskFilterCardProps {
1817 ids ?: TaskIdExamples ;
19- filters ?: unknown ;
18+ filters ?: string [ ] | null ;
2019 updateFilters : ( values : TaskIdFilterValues ) => void ;
2120 resetFilterHook : ( resetFn : ( ) => void ) => void ;
2221}
@@ -25,14 +24,12 @@ interface TaskFilterCardState {
2524 values : TaskIdFilterValues ;
2625}
2726
28- let debounceHandler : ReturnType < typeof setTimeout > = setTimeout ( ( ) => {
29- /* empty */
30- } , 500 ) ;
31-
3227export default class TaskFilterCard extends React . PureComponent <
33- TaskFilterCardProps ,
34- TaskFilterCardState
28+ Readonly < TaskFilterCardProps > ,
29+ Readonly < TaskFilterCardState >
3530> {
31+ private debounceHandler ?: ReturnType < typeof setTimeout > ;
32+
3633 constructor ( props : TaskFilterCardProps ) {
3734 super ( props ) ;
3835 this . state = {
@@ -51,16 +48,18 @@ export default class TaskFilterCard extends React.PureComponent<
5148 }
5249
5350 extractFilters ( ) : TaskIdFilterValues {
54- let i = 0 ;
51+ // NOTE (JS->TS): Directly access filters array and convert to TaskIdFilterValues object for better type safety and readability.
52+ // Using forEach and optional chaining eliminates the need for external pathOr utility and manual type casting.
5553 const newVal : TaskIdFilterValues = { } ;
5654 const ids = this . props . ids ?? { } ;
57- for ( const id of Object . keys ( ids ) ) {
58- newVal [ id ] = pathOr ( [ "filters" , i ++ ] , "" , this . props ) as string ;
59- }
55+ const filters = this . props . filters ;
56+ Object . keys ( ids ) . forEach ( ( id , i ) => {
57+ newVal [ id ] = filters ?. [ i ] ?? "" ;
58+ } ) ;
6059 return newVal ;
6160 }
6261
63- componentDidUpdate ( prevProps : TaskFilterCardProps ) : void {
62+ componentDidUpdate ( prevProps : Readonly < TaskFilterCardProps > ) : void {
6463 if ( ! equals ( this . props . filters , prevProps . filters ) ) {
6564 const newVal = this . extractFilters ( ) ;
6665 this . setState ( { values : newVal } ) ;
@@ -93,11 +92,15 @@ export default class TaskFilterCard extends React.PureComponent<
9392 onChange = { ( {
9493 target : { value : textValue } ,
9594 } : React . ChangeEvent < HTMLInputElement > ) => {
96- clearTimeout ( debounceHandler ) ;
95+ // NOTE (JS->TS): Use a class-level debounce handler to avoid global side effects and ensure multiple instances
96+ // of this component don't interfere with each other's timers.
97+ if ( this . debounceHandler ) {
98+ clearTimeout ( this . debounceHandler ) ;
99+ }
97100 const newState : TaskFilterCardState = {
98101 values : { ...this . state . values , [ key ] : textValue } ,
99102 } ;
100- debounceHandler = setTimeout ( ( ) => {
103+ this . debounceHandler = setTimeout ( ( ) => {
101104 this . sendFilterUpdate ( {
102105 ...this . state . values ,
103106 [ key ] : textValue ,
0 commit comments