@@ -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,26 @@ export const MovesByRating: React.FC<Props> = ({
115139 >
116140 < stop
117141 offset = "5%"
118- stopColor = { colorSanMapping [ move ] ?. color ?? '#fff' }
142+ stopColor = {
143+ displayedColorSanMapping [ move ] ?. color ?? '#fff'
144+ }
119145 stopOpacity = { 0.5 }
120146 />
121147 < stop
122148 offset = "95%"
123- stopColor = { colorSanMapping [ move ] ?. color ?? '#fff' }
149+ stopColor = {
150+ displayedColorSanMapping [ move ] ?. color ?? '#fff'
151+ }
124152 stopOpacity = { 0 }
125153 />
126154 </ linearGradient >
127155 )
128156 } ) }
129157 </ defs >
130- { moves &&
158+ { displayedMoves &&
131159 // First, collect all the end points and sort them by y-position
132160 ( ( ) => {
133- const lastIndex = moves . length - 1
161+ const lastIndex = displayedMoves . length - 1
134162
135163 // Define the type for end points
136164 interface EndPoint {
@@ -142,42 +170,38 @@ export const MovesByRating: React.FC<Props> = ({
142170 adjustment ?: number
143171 }
144172
145- const endPoints = Object . keys ( moves [ 0 ] )
146- . filter ( ( move ) => move !== 'rating' )
173+ const endPoints = moveKeys
147174 . map ( ( move ) => {
148- const value = moves [ lastIndex ] [ move ] as number
175+ const value = displayedMoves [ lastIndex ] [ move ] as number
149176 return {
150177 move,
151178 value,
152- san : colorSanMapping [ move ] ?. san || move ,
153- color : colorSanMapping [ move ] ?. color ?? '#fff' ,
179+ san : displayedColorSanMapping [ move ] ?. san || move ,
180+ color : displayedColorSanMapping [ move ] ?. color ?? '#fff' ,
154181 } as EndPoint
155182 } )
156183 . sort ( ( a , b ) => a . value - b . value ) // Sort by value (y-position)
157184
158185 // 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-
186+ return moveKeys . map ( ( move , index ) => {
164187 const endPoint = endPoints . find ( ( ep ) => ep . move === move )
165188 const san = endPoint ?. san || move
166189
167190 return (
168191 < Area
169- key = { i }
192+ key = { index }
170193 yAxisId = "left"
171194 dataKey = { move }
172195 dot = { {
173196 r : isMobile ? 2 : 3 ,
174- stroke : colorSanMapping [ move ] ?. color ?? '#fff' ,
197+ stroke : displayedColorSanMapping [ move ] ?. color ?? '#fff' ,
175198 strokeWidth : isMobile ? 2 : 3 ,
176199 } }
177- stroke = { colorSanMapping [ move ] ?. color ?? '#fff' }
200+ stroke = { displayedColorSanMapping [ move ] ?. color ?? '#fff' }
178201 fill = { `url(#color${ move } )` }
179202 strokeWidth = { isMobile ? 2 : 3 }
180203 animationDuration = { 300 }
204+ isAnimationActive = { shouldAnimateSeries }
181205 name = { san }
182206 label = { ( props : {
183207 x : number
@@ -231,7 +255,7 @@ export const MovesByRating: React.FC<Props> = ({
231255 dy = { isMobile ? 3 : 4 }
232256 fontSize = { 11 }
233257 fontWeight = { 600 }
234- fill = { colorSanMapping [ move ] ?. color ?? '#fff' }
258+ fill = { displayedColorSanMapping [ move ] ?. color ?? '#fff' }
235259 textAnchor = "start"
236260 >
237261 { san }
@@ -298,8 +322,8 @@ export const MovesByRating: React.FC<Props> = ({
298322 fontSize : 14 ,
299323 } }
300324 iconSize = { 0 }
301- formatter = { ( value ) => {
302- return colorSanMapping [ value as string ] ?. san ?? value
325+ formatter = { ( value : string ) => {
326+ return displayedColorSanMapping [ value as string ] ?. san ?? value
303327 } }
304328 />
305329 </ AreaChart >
0 commit comments