@@ -8,26 +8,53 @@ import {
88 CartesianGrid ,
99 ResponsiveContainer ,
1010} from 'recharts'
11- import { useContext } from 'react'
11+ import { useContext , useEffect , useMemo , useRef , useState } from 'react'
1212import { ColorSanMapping } from 'src/types'
1313import { WindowSizeContext } from 'src/contexts'
1414
1515interface Props {
1616 moves : { [ key : string ] : number } [ ] | undefined
1717 colorSanMapping : ColorSanMapping
1818 isHomePage ?: boolean
19+ positionKey ?: string
1920}
2021
2122export const MovesByRating : React . FC < Props > = ( {
2223 moves,
2324 colorSanMapping,
2425 isHomePage = false ,
26+ positionKey,
2527} : Props ) => {
2628 const { isMobile } = useContext ( WindowSizeContext )
29+ const [ displayedMoves , setDisplayedMoves ] = useState ( moves )
30+ const [ displayedColorSanMapping , setDisplayedColorSanMapping ] =
31+ useState ( colorSanMapping )
32+ const [ displayedPositionKey , setDisplayedPositionKey ] = useState ( positionKey )
33+ const lastRenderedPositionKeyRef = useRef < string | undefined > ( positionKey )
34+ const shouldAnimateSeries =
35+ ! ! displayedPositionKey &&
36+ displayedPositionKey !== lastRenderedPositionKeyRef . current
2737
28- const maxValue = moves
38+ useEffect ( ( ) => {
39+ if ( ! moves ?. length || ! positionKey ) return
40+ setDisplayedMoves ( moves )
41+ setDisplayedColorSanMapping ( colorSanMapping )
42+ setDisplayedPositionKey ( positionKey )
43+ } , [ moves , colorSanMapping , positionKey ] )
44+
45+ useEffect ( ( ) => {
46+ if ( ! displayedPositionKey ) return
47+ lastRenderedPositionKeyRef . current = displayedPositionKey
48+ } , [ displayedPositionKey ] )
49+
50+ const moveKeys = useMemo ( ( ) => {
51+ if ( ! displayedMoves ?. length ) return [ ]
52+ return Object . keys ( displayedMoves [ 0 ] ) . filter ( ( move ) => move !== 'rating' )
53+ } , [ displayedMoves ] )
54+
55+ const maxValue = displayedMoves
2956 ? Math . max (
30- ...moves . flatMap ( ( move ) =>
57+ ...displayedMoves . flatMap ( ( move ) =>
3158 Object . entries ( move )
3259 . filter ( ( [ key ] ) => key !== 'rating' )
3360 . map ( ( [ , value ] ) => value as number ) ,
@@ -48,7 +75,7 @@ export const MovesByRating: React.FC<Props> = ({
4875 </ h2 >
4976 < ResponsiveContainer width = "100%" height = "90%" >
5077 < AreaChart
51- data = { moves }
78+ data = { displayedMoves }
5279 margin = { {
5380 left : 0 ,
5481 right : isMobile ? 40 : 50 ,
@@ -99,11 +126,8 @@ export const MovesByRating: React.FC<Props> = ({
99126 tickFormatter = { ( value ) => `${ value } %` }
100127 />
101128 < defs >
102- { moves &&
103- Object . keys ( moves [ 0 ] ) . map ( ( move , i ) => {
104- if ( move === 'rating' ) {
105- return null
106- }
129+ { displayedMoves &&
130+ moveKeys . map ( ( move ) => {
107131 return (
108132 < linearGradient
109133 key = { `color${ move } ` }
@@ -115,22 +139,22 @@ export const MovesByRating: React.FC<Props> = ({
115139 >
116140 < stop
117141 offset = "5%"
118- stopColor = { colorSanMapping [ move ] ?. color ?? '#fff' }
142+ stopColor = { displayedColorSanMapping [ move ] ?. color ?? '#fff' }
119143 stopOpacity = { 0.5 }
120144 />
121145 < stop
122146 offset = "95%"
123- stopColor = { colorSanMapping [ move ] ?. color ?? '#fff' }
147+ stopColor = { displayedColorSanMapping [ move ] ?. color ?? '#fff' }
124148 stopOpacity = { 0 }
125149 />
126150 </ linearGradient >
127151 )
128152 } ) }
129153 </ defs >
130- { moves &&
154+ { displayedMoves &&
131155 // First, collect all the end points and sort them by y-position
132156 ( ( ) => {
133- const lastIndex = moves . length - 1
157+ const lastIndex = displayedMoves . length - 1
134158
135159 // Define the type for end points
136160 interface EndPoint {
@@ -142,42 +166,38 @@ export const MovesByRating: React.FC<Props> = ({
142166 adjustment ?: number
143167 }
144168
145- const endPoints = Object . keys ( moves [ 0 ] )
146- . filter ( ( move ) => move !== 'rating' )
169+ const endPoints = moveKeys
147170 . map ( ( move ) => {
148- const value = moves [ lastIndex ] [ move ] as number
171+ const value = displayedMoves [ lastIndex ] [ move ] as number
149172 return {
150173 move,
151174 value,
152- san : colorSanMapping [ move ] ?. san || move ,
153- color : colorSanMapping [ move ] ?. color ?? '#fff' ,
175+ san : displayedColorSanMapping [ move ] ?. san || move ,
176+ color : displayedColorSanMapping [ move ] ?. color ?? '#fff' ,
154177 } as EndPoint
155178 } )
156179 . sort ( ( a , b ) => a . value - b . value ) // Sort by value (y-position)
157180
158181 // Return the original map function with adjusted positions
159- return Object . keys ( moves [ 0 ] ) . map ( ( move , i ) => {
160- if ( move === 'rating' ) {
161- return null
162- }
163-
182+ return moveKeys . map ( ( move , index ) => {
164183 const endPoint = endPoints . find ( ( ep ) => ep . move === move )
165184 const san = endPoint ?. san || move
166185
167186 return (
168187 < Area
169- key = { i }
188+ key = { index }
170189 yAxisId = "left"
171190 dataKey = { move }
172191 dot = { {
173192 r : isMobile ? 2 : 3 ,
174- stroke : colorSanMapping [ move ] ?. color ?? '#fff' ,
193+ stroke : displayedColorSanMapping [ move ] ?. color ?? '#fff' ,
175194 strokeWidth : isMobile ? 2 : 3 ,
176195 } }
177- stroke = { colorSanMapping [ move ] ?. color ?? '#fff' }
196+ stroke = { displayedColorSanMapping [ move ] ?. color ?? '#fff' }
178197 fill = { `url(#color${ move } )` }
179198 strokeWidth = { isMobile ? 2 : 3 }
180199 animationDuration = { 300 }
200+ isAnimationActive = { shouldAnimateSeries }
181201 name = { san }
182202 label = { ( props : {
183203 x : number
@@ -231,7 +251,7 @@ export const MovesByRating: React.FC<Props> = ({
231251 dy = { isMobile ? 3 : 4 }
232252 fontSize = { 11 }
233253 fontWeight = { 600 }
234- fill = { colorSanMapping [ move ] ?. color ?? '#fff' }
254+ fill = { displayedColorSanMapping [ move ] ?. color ?? '#fff' }
235255 textAnchor = "start"
236256 >
237257 { san }
@@ -298,8 +318,8 @@ export const MovesByRating: React.FC<Props> = ({
298318 fontSize : 14 ,
299319 } }
300320 iconSize = { 0 }
301- formatter = { ( value ) => {
302- return colorSanMapping [ value as string ] ?. san ?? value
321+ formatter = { ( value : string ) => {
322+ return displayedColorSanMapping [ value as string ] ?. san ?? value
303323 } }
304324 />
305325 </ AreaChart >
0 commit comments