@@ -29,24 +29,6 @@ export const UserSearch: React.FC<UserSearchProps> = ({
2929 const router = useRouter ( ) ;
3030 const shortcodeURLParam = useMemo ( ( ) => searchParams . get ( "shortcode" ) || "" , [ searchParams ] ) ;
3131
32- const fetchPurchases = useCallback ( async ( shortcode : string ) => {
33- const res = await fetch ( `/api/purchases/${ shortcode } ` , {
34- next : { tags : [ `purchases:${ shortcode } ` ] } ,
35- } ) ;
36- if ( ! res . ok ) {
37- setError ( "An error occurred" ) ;
38- return ;
39- }
40-
41- const purchases = await res . json ( ) ;
42- if ( purchases . status === "error" ) {
43- setError ( purchases . message ) ;
44- setPurchases ( [ ] ) ;
45- } else {
46- setPurchases ( purchases . orders ) ;
47- }
48- } , [ ] ) ;
49-
5032 // Form
5133 // 2 fields: shortcode & academic year purcahses.
5234 // Default value of shortcode is from the URL if possible
@@ -60,26 +42,67 @@ export const UserSearch: React.FC<UserSearchProps> = ({
6042 } ,
6143 } ,
6244 } ) ;
45+
46+ const fetchPurchases = useCallback (
47+ async ( shortcode : string ) => {
48+ const res = await fetch (
49+ `/api/purchases/${ shortcode } ?` +
50+ new URLSearchParams ( {
51+ academicYears : form . getValues ( ) . academicYears . join ( "," ) ,
52+ } ) ,
53+ {
54+ next : { tags : [ `purchases:${ shortcode } ` ] } ,
55+ } ,
56+ ) ;
57+ if ( ! res . ok ) {
58+ setError ( "An error occurred" ) ;
59+ return ;
60+ }
61+
62+ const purchases = await res . json ( ) ;
63+ if ( purchases . status === "error" ) {
64+ setError ( purchases . message ) ;
65+ setPurchases ( [ ] ) ;
66+ } else {
67+ setPurchases ( purchases . orders ) ;
68+ }
69+ } ,
70+ [ form ] ,
71+ ) ;
72+
73+ // This looks a bit weird, but effectively prevent an infinite loop of fetching purchases
74+ const [ prevURLParam , setPrevURLParam ] = useState ( shortcodeURLParam ) ;
6375 useEffect ( ( ) => {
64- if ( shortcodeURLParam ) {
65- fetchPurchases ( shortcodeURLParam ) ;
66- } else {
67- setPurchases ( [ ] ) ;
68- form . setFieldValue ( "shortcode" , "" ) ;
76+ if ( ! shortcodeURLParam ) {
77+ // only allow one rerender when the shortcode is clear
78+ // by tracking the previous value
79+ if ( prevURLParam ) {
80+ setPurchases ( [ ] ) ;
81+ form . setFieldValue ( "shortcode" , "" ) ;
82+ setPrevURLParam ( "" ) ;
83+ }
84+ }
85+ } , [ shortcodeURLParam , prevURLParam , form ] ) ;
86+
87+ // Fetch purchases if academic year changes
88+ form . watch ( "academicYears" , ( academicYears ) => {
89+ if ( form . getValues ( ) . shortcode ) {
90+ startTransition ( async ( ) => {
91+ setError ( null ) ;
92+ await fetchPurchases ( form . getValues ( ) . shortcode ) ;
93+ } ) ;
6994 }
70- // can't add form as would cause infinite loop
71- // eslint-disable-next-line react-hooks/exhaustive-deps
72- } , [ shortcodeURLParam , fetchPurchases ] ) ;
95+ } ) ;
7396
7497 const submitAction = useCallback (
7598 ( { shortcode } : { shortcode : string } ) => {
76- startTransition ( ( ) => {
99+ startTransition ( async ( ) => {
77100 setError ( null ) ;
78-
101+ await fetchPurchases ( shortcode ) ;
79102 router . push ( "/?shortcode=" + shortcode ) ;
80103 } ) ;
81104 } ,
82- [ router ] ,
105+ [ router , fetchPurchases ] ,
83106 ) ;
84107
85108 return (
@@ -96,6 +119,7 @@ export const UserSearch: React.FC<UserSearchProps> = ({
96119 alignItems : "center" ,
97120 } }
98121 onSubmit = { form . onSubmit ( submitAction ) }
122+ // eslint-disable-next-line @typescript-eslint/no-empty-function
99123 action = { ( ) => { } }
100124 >
101125 < Group w = "100%" >
@@ -115,6 +139,7 @@ export const UserSearch: React.FC<UserSearchProps> = ({
115139 < Button
116140 color = "pink"
117141 onClick = { ( ) => {
142+ setPurchases ( [ ] ) ;
118143 router . push ( "/" ) ;
119144 } }
120145 >
0 commit comments