Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita2d3eb5

Browse files
committed
fix(CDropdown): prevent unnecessary re-rendering
1 parent90d8100 commita2d3eb5

File tree

3 files changed

+63
-62
lines changed

3 files changed

+63
-62
lines changed

‎packages/coreui-react/src/components/dropdown/CDropdown.tsx‎

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
1-
importReact,{ElementType,forwardRef,HTMLAttributes,useEffect,useRef,useState}from'react'
1+
importReact,{
2+
ElementType,
3+
forwardRef,
4+
HTMLAttributes,
5+
useCallback,
6+
useEffect,
7+
useMemo,
8+
useRef,
9+
useState,
10+
}from'react'
211
importPropTypesfrom'prop-types'
312
importclassNamesfrom'classnames'
413
importtype{Options}from'@popperjs/core'
@@ -190,59 +199,63 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
190199
ref
191200
)=>{
192201
constdropdownRef=useRef<HTMLDivElement>(null)
193-
constdropdownToggleRef=useRef<HTMLElement>(null)
194202
constdropdownMenuRef=useRef<HTMLDivElement|HTMLUListElement>(null)
195203
constforkedRef=useForkedRef(ref,dropdownRef)
204+
const[dropdownToggleElement,setDropdownToggleElement]=useState<HTMLElement|null>(null)
196205
const[_visible,setVisible]=useState(visible)
197206
const{ initPopper, destroyPopper}=usePopper()
198207

199-
constComponent=variant==='nav-item' ?'li' :as
208+
constdropdownToggleRef=useCallback((node:HTMLElement|null)=>{
209+
if(node){
210+
setDropdownToggleElement(node)
211+
}
212+
},[])
200213

201-
// Disable popper if responsive aligment is set.
202-
if(typeofalignment==='object'){
203-
popper=false
204-
}
214+
constallowPopperUse=popper&&typeofalignment!=='object'
215+
constComponent=variant==='nav-item' ?'li' :as
205216

206217
constcontextValues={
207218
alignment,
208219
container,
209220
dark,
210-
dropdownToggleRef,
211221
dropdownMenuRef,
212-
popper,
222+
dropdownToggleRef,
223+
popper:allowPopperUse,
213224
portal,
214225
variant,
215226
visible:_visible,
216227
setVisible,
217228
}
218229

219-
constdefaultPopperConfig={
220-
modifiers:[
221-
{
222-
name:'offset',
223-
options:{
224-
offset:offset,
230+
constcomputedPopperConfig:Partial<Options>=useMemo(()=>{
231+
constdefaultPopperConfig={
232+
modifiers:[
233+
{
234+
name:'offset',
235+
options:{
236+
offset,
237+
},
225238
},
226-
},
227-
],
228-
placement:getPlacement(placement,direction,alignment,isRTL(dropdownMenuRef.current)),
229-
}
239+
],
240+
placement:getPlacement(placement,direction,alignment,isRTL(dropdownMenuRef.current)),
241+
}
230242

231-
constcomputedPopperConfig:Partial<Options>={
232-
...defaultPopperConfig,
233-
...(typeofpopperConfig==='function' ?popperConfig(defaultPopperConfig) :popperConfig),
234-
}
243+
return{
244+
...defaultPopperConfig,
245+
...(typeofpopperConfig==='function' ?popperConfig(defaultPopperConfig) :popperConfig),
246+
}
247+
},[offset,placement,direction,alignment,popperConfig])
235248

236249
useEffect(()=>{
237250
setVisible(visible)
238251
},[visible])
239252

240253
useEffect(()=>{
241-
consttoggleElement=dropdownToggleRef.current
254+
consttoggleElement=dropdownToggleElement
242255
constmenuElement=dropdownMenuRef.current
243256

244257
if(_visible&&toggleElement&&menuElement){
245-
if(popper){
258+
if(allowPopperUse){
246259
initPopper(toggleElement,menuElement,computedPopperConfig)
247260
}
248261

@@ -257,7 +270,7 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
257270
}
258271

259272
return()=>{
260-
if(popper){
273+
if(allowPopperUse){
261274
destroyPopper()
262275
}
263276

@@ -269,14 +282,7 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
269282

270283
onHide?.()
271284
}
272-
},[
273-
computedPopperConfig,
274-
destroyPopper,
275-
dropdownMenuRef,
276-
dropdownToggleRef,
277-
initPopper,
278-
_visible,
279-
])
285+
},[dropdownToggleElement,_visible])
280286

281287
consthandleKeydown=(event:KeyboardEvent)=>{
282288
if(
@@ -304,11 +310,11 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
304310
}
305311

306312
consthandleMouseUp=(event:Event)=>{
307-
if(!dropdownToggleRef.current||!dropdownMenuRef.current){
313+
if(!dropdownToggleElement||!dropdownMenuRef.current){
308314
return
309315
}
310316

311-
if(dropdownToggleRef.current.contains(event.targetasHTMLElement)){
317+
if(dropdownToggleElement.contains(event.targetasHTMLElement)){
312318
return
313319
}
314320

‎packages/coreui-react/src/components/dropdown/CDropdownContext.ts‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ export interface CDropdownContextProps {
55
alignment?:Alignments
66
container?:DocumentFragment|Element|(()=>DocumentFragment|Element|null)|null
77
dark?:boolean
8-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
9-
dropdownToggleRef:RefObject<any|null>
108
dropdownMenuRef:RefObject<HTMLDivElement|HTMLUListElement|null>
9+
dropdownToggleRef:(node:HTMLElement|null)=>void
1110
setVisible:React.Dispatch<React.SetStateAction<boolean|undefined>>
1211
popper?:boolean
1312
portal?:boolean

‎packages/coreui-react/src/components/dropdown/CDropdownToggle.tsx‎

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -74,36 +74,32 @@ export const CDropdownToggle: FC<CDropdownToggleProps> = ({
7474
...(!rest.disabled&&{ ...triggers}),
7575
}
7676

77-
constToggler=()=>{
78-
if(custom&&React.isValidElement(children)){
79-
return(
80-
<>
81-
{React.cloneElement(childrenasReact.ReactElement<any>,{
82-
'aria-expanded':visible,
83-
...(!rest.disabled&&{ ...triggers}),
84-
ref:dropdownToggleRef,
85-
})}
86-
</>
87-
)
88-
}
89-
90-
if(variant==='nav-item'&&navLink){
91-
return(
92-
<ahref="#"{...togglerProps}role="button"{...rest}ref={dropdownToggleRef}>
93-
{children}
94-
</a>
95-
)
96-
}
77+
if(custom&&React.isValidElement(children)){
78+
return(
79+
<>
80+
{React.cloneElement(childrenasReact.ReactElement<any>,{
81+
'aria-expanded':visible,
82+
...(!rest.disabled&&{ ...triggers}),
83+
ref:dropdownToggleRef,
84+
})}
85+
</>
86+
)
87+
}
9788

89+
if(variant==='nav-item'&&navLink){
9890
return(
99-
<CButton{...togglerProps}tabIndex={0}{...rest}ref={dropdownToggleRef}>
91+
<ahref="#"{...togglerProps}role="button"{...rest}ref={dropdownToggleRef}>
10092
{children}
101-
{split&&<spanclassName="visually-hidden">Toggle Dropdown</span>}
102-
</CButton>
93+
</a>
10394
)
10495
}
10596

106-
return<Toggler/>
97+
return(
98+
<CButton{...togglerProps}tabIndex={0}{...rest}ref={dropdownToggleRef}>
99+
{children}
100+
{split&&<spanclassName="visually-hidden">Toggle Dropdown</span>}
101+
</CButton>
102+
)
107103
}
108104

109105
CDropdownToggle.propTypes={

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp