55 REACTION_TYPE ,
66 ReactionStatus as ReactionStatusModel ,
77} from "@/backend/models/domain-models" ;
8+ import { useImmer } from "use-immer" ;
89
910interface Props {
1011 resource_type : "ARTICLE" | "COMMENT" ;
@@ -26,6 +27,38 @@ const ReactionStatus: React.FC<Props> = ({
2627 render,
2728} ) => {
2829 const queryClient = useQueryClient ( ) ;
30+ const [ reactions , setReactions ] = useImmer < ReactionStatusModel [ ] > ( [
31+ {
32+ count : 0 ,
33+ is_reacted : false ,
34+ reaction_type : "CRY" ,
35+ } ,
36+ {
37+ count : 0 ,
38+ is_reacted : false ,
39+ reaction_type : "FIRE" ,
40+ } ,
41+ {
42+ count : 0 ,
43+ is_reacted : false ,
44+ reaction_type : "HAHA" ,
45+ } ,
46+ {
47+ count : 0 ,
48+ is_reacted : false ,
49+ reaction_type : "LOVE" ,
50+ } ,
51+ {
52+ count : 0 ,
53+ is_reacted : false ,
54+ reaction_type : "UNICORN" ,
55+ } ,
56+ {
57+ count : 0 ,
58+ is_reacted : false ,
59+ reaction_type : "WOW" ,
60+ } ,
61+ ] ) ;
2962
3063 const query = useQuery ( {
3164 queryKey : [ "reaction" , resource_id , resource_type ] ,
@@ -40,66 +73,42 @@ const ReactionStatus: React.FC<Props> = ({
4073 resource_type,
4174 reaction_type,
4275 } ) ,
43- onMutate : async ( reaction_type : REACTION_TYPE ) => {
44- // Cancel any outgoing refetches
76+ async onMutate ( reaction_type ) {
77+ // cancel
4578 await queryClient . cancelQueries ( {
4679 queryKey : [ "reaction" , resource_id , resource_type ] ,
4780 } ) ;
4881
49- // Snapshot the previous value
50- const previousReactions = queryClient . getQueryData < ReactionStatusModel [ ] > (
51- [ "reaction" , resource_id , resource_type ]
52- ) ;
82+ const oldReactions = queryClient . getQueryData ( [
83+ "reaction" ,
84+ resource_id ,
85+ resource_type ,
86+ ] ) ;
5387
54- // Optimistically update to the new value
55- queryClient . setQueryData < ReactionStatusModel [ ] > (
88+ queryClient . setQueryData (
5689 [ "reaction" , resource_id , resource_type ] ,
57- ( old = [ ] ) => {
58- const existingReaction = old . find (
59- ( r ) => r . reaction_type === reaction_type
60- ) ;
61-
62- if ( existingReaction ) {
63- // If reaction exists, toggle it (remove if active, or toggle status)
64- if ( existingReaction . is_reacted ) {
65- // Remove the reaction
66- return old . filter ( ( r ) => r . reaction_type !== reaction_type ) ;
67- } else {
68- // Activate the reaction
69- return old . map ( ( r ) =>
70- r . reaction_type === reaction_type
71- ? { ...r , is_active : true , count : r . count + 1 }
72- : r
73- ) ;
74- }
90+ ( old : ReactionStatusModel [ ] ) => {
91+ const index = old . findIndex ( ( r ) => r . reaction_type == reaction_type ) ;
92+ if ( old [ index ] . is_reacted ) {
93+ old [ index ] . is_reacted = false ;
94+ -- old [ index ] . count ;
7595 } else {
76- // Add new reaction
77- return [
78- ...old ,
79- {
80- reaction_type,
81- is_reacted : true ,
82- count : 1 ,
83- resource_id,
84- resource_type,
85- } as ReactionStatusModel ,
86- ] ;
96+ old [ index ] . is_reacted = true ;
97+ ++ old [ index ] . count ;
8798 }
99+ return old ;
88100 }
89101 ) ;
90102
91- // Return a context object with the snapshotted value
92- return { previousReactions } ;
103+ return { oldReactions } ;
93104 } ,
94- onError : ( err , reaction_type , context ) => {
95- // If the mutation fails, use the context returned from onMutate to roll back
105+ onError : ( _ , __ , context ) => {
96106 queryClient . setQueryData (
97107 [ "reaction" , resource_id , resource_type ] ,
98- context ?. previousReactions
108+ context ?. oldReactions
99109 ) ;
100110 } ,
101111 onSettled : ( ) => {
102- // Always refetch after error or success to ensure we have the latest data
103112 queryClient . invalidateQueries ( {
104113 queryKey : [ "reaction" , resource_id , resource_type ] ,
105114 } ) ;
0 commit comments