1- import React , { ElementType , forwardRef , HTMLAttributes , useEffect , useRef , useState } from 'react'
1+ import React , {
2+ ElementType ,
3+ forwardRef ,
4+ HTMLAttributes ,
5+ useCallback ,
6+ useEffect ,
7+ useMemo ,
8+ useRef ,
9+ useState ,
10+ } from 'react'
211import PropTypes from 'prop-types'
312import classNames from 'classnames'
413import type { Options } from '@popperjs/core'
@@ -190,59 +199,63 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
190199ref
191200) => {
192201const dropdownRef = useRef < HTMLDivElement > ( null )
193- const dropdownToggleRef = useRef < HTMLElement > ( null )
194202const dropdownMenuRef = useRef < HTMLDivElement | HTMLUListElement > ( null )
195203const forkedRef = useForkedRef ( ref , dropdownRef )
204+ const [ dropdownToggleElement , setDropdownToggleElement ] = useState < HTMLElement | null > ( null )
196205const [ _visible , setVisible ] = useState ( visible )
197206const { initPopper, destroyPopper} = usePopper ( )
198207
199- const Component = variant === 'nav-item' ?'li' :as
208+ const dropdownToggleRef = useCallback ( ( node :HTMLElement | null ) => {
209+ if ( node ) {
210+ setDropdownToggleElement ( node )
211+ }
212+ } , [ ] )
200213
201- // Disable popper if responsive aligment is set.
202- if ( typeof alignment === 'object' ) {
203- popper = false
204- }
214+ const allowPopperUse = popper && typeof alignment !== 'object'
215+ const Component = variant === 'nav-item' ?'li' :as
205216
206217const contextValues = {
207218 alignment,
208219 container,
209220 dark,
210- dropdownToggleRef,
211221 dropdownMenuRef,
212- popper,
222+ dropdownToggleRef,
223+ popper :allowPopperUse ,
213224 portal,
214225 variant,
215226visible :_visible ,
216227 setVisible,
217228}
218229
219- const defaultPopperConfig = {
220- modifiers :[
221- {
222- name :'offset' ,
223- options :{
224- offset :offset ,
230+ const computedPopperConfig :Partial < Options > = useMemo ( ( ) => {
231+ const defaultPopperConfig = {
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- const computedPopperConfig :Partial < Options > = {
232- ...defaultPopperConfig ,
233- ...( typeof popperConfig === 'function' ?popperConfig ( defaultPopperConfig ) :popperConfig ) ,
234- }
243+ return {
244+ ...defaultPopperConfig ,
245+ ...( typeof popperConfig === 'function' ?popperConfig ( defaultPopperConfig ) :popperConfig ) ,
246+ }
247+ } , [ offset , placement , direction , alignment , popperConfig ] )
235248
236249useEffect ( ( ) => {
237250setVisible ( visible )
238251} , [ visible ] )
239252
240253useEffect ( ( ) => {
241- const toggleElement = dropdownToggleRef . current
254+ const toggleElement = dropdownToggleElement
242255const menuElement = dropdownMenuRef . current
243256
244257if ( _visible && toggleElement && menuElement ) {
245- if ( popper ) {
258+ if ( allowPopperUse ) {
246259initPopper ( toggleElement , menuElement , computedPopperConfig )
247260}
248261
@@ -257,7 +270,7 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
257270}
258271
259272return ( ) => {
260- if ( popper ) {
273+ if ( allowPopperUse ) {
261274destroyPopper ( )
262275}
263276
@@ -269,14 +282,7 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
269282
270283onHide ?.( )
271284}
272- } , [
273- computedPopperConfig ,
274- destroyPopper ,
275- dropdownMenuRef ,
276- dropdownToggleRef ,
277- initPopper ,
278- _visible ,
279- ] )
285+ } , [ dropdownToggleElement , _visible ] )
280286
281287const handleKeydown = ( event :KeyboardEvent ) => {
282288if (
@@ -304,11 +310,11 @@ export const CDropdown: PolymorphicRefForwardingComponent<'div', CDropdownProps>
304310}
305311
306312const handleMouseUp = ( event :Event ) => {
307- if ( ! dropdownToggleRef . current || ! dropdownMenuRef . current ) {
313+ if ( ! dropdownToggleElement || ! dropdownMenuRef . current ) {
308314return
309315}
310316
311- if ( dropdownToggleRef . current . contains ( event . target as HTMLElement ) ) {
317+ if ( dropdownToggleElement . contains ( event . target as HTMLElement ) ) {
312318return
313319}
314320