Skip to content

Commit

Permalink
fix Controlled state by ensuring dependency Ref is kept in sync with …
Browse files Browse the repository at this point in the history
…state
  • Loading branch information
chad1008 committed Jun 22, 2022
1 parent e1406fa commit a1ac5de
Showing 1 changed file with 13 additions and 9 deletions.
22 changes: 13 additions & 9 deletions packages/components/src/navigation/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ import classnames from 'classnames';
/**
* WordPress dependencies
*/
import { useEffect, useRef, useState } from '@wordpress/element';
import {
useEffect,
useLayoutEffect,
useRef,
useState,
} from '@wordpress/element';
import { isRTL } from '@wordpress/i18n';

/**
Expand All @@ -28,7 +33,6 @@ export default function Navigation( {
onActivateMenu = noop,
} ) {
const [ menu, setMenu ] = useState( activeMenu );
const menuRef = useRef( activeMenu );
const [ slideOrigin, setSlideOrigin ] = useState();
const navigationTree = useCreateNavigationTree();
const defaultSlideOrigin = isRTL() ? 'right' : 'left';
Expand All @@ -51,15 +55,15 @@ export default function Navigation( {
}
}, [] );

useEffect( () => {
menuRef.current = menu;
}, [ menu ] );
// Used to prevent excessive useEffect fires when navigation is being controlled by parent component
const controlledMenuUpdate = useRef( { setActiveMenu, menu } );
useLayoutEffect( () => {
controlledMenuUpdate.current = { setActiveMenu, menu };
} );

// Used to prevent resetting the `menu` state when navigating between menus
const setActiveMenuRef = useRef( setActiveMenu );
useEffect( () => {
if ( activeMenu !== menuRef.current ) {
setActiveMenuRef.current( activeMenu );
if ( activeMenu !== controlledMenuUpdate.current.menu ) {
controlledMenuUpdate.current.setActiveMenu( activeMenu );
}
}, [ activeMenu ] );

Expand Down

0 comments on commit a1ac5de

Please sign in to comment.