1- import { useRef } from 'react' ;
1+ import { useMemo , useRef } from 'react' ;
22import { AnimatePresence , Reorder } from 'framer-motion' ;
33
44import { GroupFields } from 'components' ;
@@ -13,6 +13,7 @@ import { useCanvas, useForceUpdate } from 'hooks';
1313import { getDeepObjectProperty , getSocialImgUrl } from 'utils' ;
1414
1515import { fields , getIconFields } from './fields' ;
16+ import React from 'react' ;
1617
1718type Social = {
1819 icon : string ;
@@ -23,6 +24,57 @@ type Socials = {
2324 [ key : string ] : Social ;
2425} ;
2526
27+ interface MemoizedIconEditorProps {
28+ social : string ;
29+ props : Social ;
30+ index : number ;
31+ iconEditorRefs : React . MutableRefObject < IconEditorRef [ ] > ;
32+ }
33+
34+ const MemoizedIconEditor = React . memo (
35+ function MemoizedIconEditor ( {
36+ social,
37+ props,
38+ index,
39+ iconEditorRefs,
40+ } : MemoizedIconEditorProps ) {
41+ const { icon, short_name } = props ;
42+
43+ return (
44+ < IconEditor
45+ key = { social }
46+ id = { social }
47+ label = { short_name ?? social }
48+ baseEditPath = "content.socials"
49+ img = { {
50+ alt : `${ social } ${ icon } logo` ,
51+ url : getSocialImgUrl ( 'icon' , social , { icon } ) ,
52+ } }
53+ slots = { {
54+ expansibleContent : ( ) => (
55+ < >
56+ { getIconFields ( social ) . map ( group => (
57+ < GroupFields key = { group . id } { ...group } />
58+ ) ) }
59+ </ >
60+ ) ,
61+ } }
62+ ref = { ref => {
63+ iconEditorRefs . current [ index ] = ref ! ;
64+ } }
65+ refs = { iconEditorRefs . current }
66+ />
67+ ) ;
68+ } ,
69+ ( prevProps : MemoizedIconEditorProps , nextProps : MemoizedIconEditorProps ) => {
70+ if ( prevProps . social !== nextProps . social ) return false ;
71+ if ( prevProps . index !== nextProps . index ) return false ;
72+ if ( prevProps . props . icon !== nextProps . props . icon ) return false ;
73+ if ( prevProps . props . short_name !== nextProps . props . short_name ) return false ;
74+ return true ;
75+ }
76+ ) ;
77+
2678export function Editing ( ) {
2779 const iconEditorRefs = useRef < IconEditorRef [ ] > ( [ ] ) ;
2880
@@ -34,8 +86,15 @@ export function Editing() {
3486 'props.content.socials'
3587 ) ! ;
3688
37- const socials = Object . entries ( selectedSocials ) ;
38- const socials_names = socials . map ( social => social [ 0 ] ) ;
89+ const socialsLength = Object . keys ( selectedSocials ) . length ;
90+
91+ const memoizedSocialData = useMemo ( ( ) => {
92+ const currentSocials = Object . entries ( selectedSocials ) ;
93+ const currentSocialsNames = currentSocials . map ( social => social [ 0 ] ) ;
94+ return { socials : currentSocials , socials_names : currentSocialsNames } ;
95+ } , [ socialsLength ] ) ;
96+
97+ const { socials, socials_names } = memoizedSocialData ;
3998
4099 function onReOrder ( order : typeof socials_names ) {
41100 const path = 'content.socials' ;
@@ -61,31 +120,13 @@ export function Editing() {
61120 < AnimatePresence >
62121 < Reorder . Group axis = "y" values = { socials_names } onReorder = { onReOrder } >
63122 { socials . map ( ( [ social , props ] , index ) => {
64- const { icon, short_name } = props ;
65-
66123 return (
67- < IconEditor
124+ < MemoizedIconEditor
68125 key = { social }
69- id = { social }
70- label = { short_name ?? social }
71- baseEditPath = "content.socials"
72- img = { {
73- alt : `${ social } ${ icon } logo` ,
74- url : getSocialImgUrl ( 'icon' , social , { icon } ) ,
75- } }
76- slots = { {
77- expansibleContent : ( ) => (
78- < >
79- { getIconFields ( social ) . map ( group => (
80- < GroupFields key = { group . id } { ...group } />
81- ) ) }
82- </ >
83- ) ,
84- } }
85- ref = { ref => {
86- iconEditorRefs . current [ index ] = ref ! ;
87- } }
88- refs = { iconEditorRefs . current }
126+ social = { social }
127+ props = { props }
128+ index = { index }
129+ iconEditorRefs = { iconEditorRefs }
89130 />
90131 ) ;
91132 } ) }
0 commit comments