@@ -12,26 +12,46 @@ type BaseProps = {
12
12
voteConfig : VoteConfig ;
13
13
loggedInUserScore ?: number ;
14
14
score ?: number ;
15
+ onScoreChange ?( newScore : number ) : void ;
15
16
} ;
16
17
17
18
type CommentProps = BaseProps & { commentId : number ; postId : number } ;
18
19
type PostProps = BaseProps & { postId : number } ;
19
20
20
21
type Props = CommentProps | PostProps ;
22
+
23
+ const getNewScore = (
24
+ prevScore : number | undefined ,
25
+ prevUserScore : number | undefined ,
26
+ newUserScore : number ,
27
+ ) => {
28
+ let newScore = prevScore ?? 0 ;
29
+ if ( newScore ) {
30
+ newScore = newScore - ( prevUserScore ?? 0 ) + newUserScore ;
31
+ }
32
+
33
+ return newScore ;
34
+ } ;
35
+
21
36
export const VoteButtons = memo (
22
37
( props : Props ) => {
23
- const totalScore = ! isComment ( props ) ? props . score : undefined ; // We only show score between vote buttons for posts, not comments
24
- const [ userScore , setUserScore ] = useState ( props . loggedInUserScore ) ;
38
+ const [ score , setScore ] = useState ( {
39
+ userScore : props . loggedInUserScore ,
40
+ totalScore : props . score ,
41
+ } ) ;
25
42
26
43
const [ { optimisticUserScore, optimisticScore } , setOptimisticUserScore ] =
27
44
useOptimistic (
28
- { optimisticUserScore : userScore , optimisticScore : totalScore } ,
45
+ {
46
+ optimisticUserScore : score . userScore ?? 0 ,
47
+ optimisticScore : score . totalScore ?? 0 ,
48
+ } ,
29
49
( prevState , newUserScore : number ) => {
30
- let newScore = prevState . optimisticScore ;
31
- if ( newScore ) {
32
- newScore =
33
- newScore - ( prevState . optimisticUserScore ?? 0 ) + newUserScore ;
34
- }
50
+ let newScore = getNewScore (
51
+ prevState . optimisticScore ,
52
+ prevState . optimisticUserScore ,
53
+ newUserScore ,
54
+ ) ;
35
55
36
56
return {
37
57
optimisticUserScore : newUserScore ,
@@ -43,6 +63,29 @@ export const VoteButtons = memo(
43
63
const upvoteResultScore = ( optimisticUserScore ?? 0 ) <= 0 ? 1 : 0 ;
44
64
const downvoteResultScore = ( optimisticUserScore ?? 0 ) >= 0 ? - 1 : 0 ;
45
65
66
+ const voteAction = async ( userScoreAfterVoting : number ) => {
67
+ setOptimisticUserScore ( userScoreAfterVoting ) ;
68
+ const action = isComment ( props )
69
+ ? voteCommentAction . bind ( null , props . commentId , userScoreAfterVoting )
70
+ : votePostAction . bind ( null , props . postId , userScoreAfterVoting ) ;
71
+ await action ( ) ;
72
+ setScore ( ( prev ) => {
73
+ const newScore = getNewScore (
74
+ prev . totalScore ,
75
+ prev . userScore ,
76
+ userScoreAfterVoting ,
77
+ ) ;
78
+
79
+ if ( props . onScoreChange ) {
80
+ props . onScoreChange ( newScore ?? 0 ) ;
81
+ }
82
+ return {
83
+ totalScore : newScore ,
84
+ userScore : userScoreAfterVoting ,
85
+ } ;
86
+ } ) ;
87
+ } ;
88
+
46
89
return (
47
90
< div
48
91
className = { classNames (
@@ -52,13 +95,7 @@ export const VoteButtons = memo(
52
95
>
53
96
< form
54
97
action = { async ( ) => {
55
- setOptimisticUserScore ( upvoteResultScore ) ;
56
-
57
- const action = isComment ( props )
58
- ? voteCommentAction . bind ( null , props . commentId , upvoteResultScore )
59
- : votePostAction . bind ( null , props . postId , upvoteResultScore ) ;
60
- await action ( ) ;
61
- setUserScore ( upvoteResultScore ) ;
98
+ await voteAction ( upvoteResultScore ) ;
62
99
} }
63
100
>
64
101
< button type = { "submit" } >
@@ -74,24 +111,15 @@ export const VoteButtons = memo(
74
111
/>
75
112
</ button >
76
113
</ form >
77
- { optimisticScore !== undefined && props . voteConfig . scoresVisible && (
114
+ { ! isComment ( props ) && props . voteConfig . scoresVisible && (
78
115
< div className = { "mb-0.5 w-8 text-center font-semibold" } >
79
116
{ formatCompactNumber ( optimisticScore ) }
80
117
</ div >
81
118
) }
82
119
{ props . voteConfig . downvotesEnabled && (
83
120
< form
84
121
action = { async ( ) => {
85
- setOptimisticUserScore ( downvoteResultScore ) ;
86
- const action = isComment ( props )
87
- ? voteCommentAction . bind (
88
- null ,
89
- props . commentId ,
90
- downvoteResultScore ,
91
- )
92
- : votePostAction . bind ( null , props . postId , downvoteResultScore ) ;
93
- await action ( ) ;
94
- setUserScore ( downvoteResultScore ) ;
122
+ await voteAction ( downvoteResultScore ) ;
95
123
} }
96
124
>
97
125
< button type = { "submit" } >
0 commit comments