2
2
* WordPress dependencies
3
3
*/
4
4
import { useSelect , useDispatch } from '@wordpress/data' ;
5
- import { useEffect } from '@wordpress/element' ;
5
+ import { useEffect , useRef } from '@wordpress/element' ;
6
6
7
7
/**
8
8
* Internal dependencies
@@ -12,32 +12,64 @@ import { unlock } from '../lock-unlock';
12
12
13
13
/**
14
14
* A hook used to set the editor mode to zoomed out mode, invoking the hook sets the mode.
15
+ * Concepts:
16
+ * - If we most recently changed the zoom level for them (in or out), we always resetZoomLevel() level when unmounting.
17
+ * - If the user most recently changed the zoom level (manually toggling), we do nothing when unmounting.
15
18
*
16
- * @param {boolean } zoomOut If we should enter into zoomOut mode or not
19
+ * @param {boolean } enabled If we should enter into zoomOut mode or not
17
20
*/
18
- export function useZoomOut ( zoomOut = true ) {
21
+ export function useZoomOut ( enabled = true ) {
19
22
const { setZoomLevel, resetZoomLevel } = unlock (
20
23
useDispatch ( blockEditorStore )
21
24
) ;
22
- const { isZoomOut } = unlock ( useSelect ( blockEditorStore ) ) ;
23
25
26
+ /**
27
+ * We need access to both the value and the function. The value is to trigger a useEffect hook
28
+ * and the function is to check zoom out within another hook without triggering a re-render.
29
+ */
30
+ const { isZoomedOut, isZoomOut } = useSelect ( ( select ) => {
31
+ const { isZoomOut : _isZoomOut } = unlock ( select ( blockEditorStore ) ) ;
32
+ return {
33
+ isZoomedOut : _isZoomOut ( ) ,
34
+ isZoomOut : _isZoomOut ,
35
+ } ;
36
+ } , [ ] ) ;
37
+
38
+ const controlZoomLevelRef = useRef ( false ) ;
39
+ const isEnabledRef = useRef ( enabled ) ;
40
+
41
+ /**
42
+ * This hook tracks if the zoom state was changed manually by the user via clicking
43
+ * the zoom out button. We only want this to run when isZoomedOut changes, so we use
44
+ * a ref to track the enabled state.
45
+ */
24
46
useEffect ( ( ) => {
25
- const isZoomOutOnMount = isZoomOut ( ) ;
47
+ // If the zoom state changed (isZoomOut) and it does not match the requested zoom
48
+ // state (zoomOut), then it means the user manually changed the zoom state while
49
+ // this hook was mounted, and we should no longer control the zoom state.
50
+ if ( isZoomedOut !== isEnabledRef . current ) {
51
+ controlZoomLevelRef . current = false ;
52
+ }
53
+ } , [ isZoomedOut ] ) ;
26
54
27
- return ( ) => {
28
- if ( isZoomOutOnMount ) {
55
+ useEffect ( ( ) => {
56
+ isEnabledRef . current = enabled ;
57
+
58
+ if ( enabled !== isZoomOut ( ) ) {
59
+ controlZoomLevelRef . current = true ;
60
+
61
+ if ( enabled ) {
29
62
setZoomLevel ( 'auto-scaled' ) ;
30
63
} else {
31
64
resetZoomLevel ( ) ;
32
65
}
33
- } ;
34
- } , [ ] ) ;
35
-
36
- useEffect ( ( ) => {
37
- if ( zoomOut ) {
38
- setZoomLevel ( 'auto-scaled' ) ;
39
- } else {
40
- resetZoomLevel ( ) ;
41
66
}
42
- } , [ zoomOut , setZoomLevel , resetZoomLevel ] ) ;
67
+
68
+ return ( ) => {
69
+ // If we are controlling zoom level and are zoomed out, reset the zoom level.
70
+ if ( controlZoomLevelRef . current && isZoomOut ( ) ) {
71
+ resetZoomLevel ( ) ;
72
+ }
73
+ } ;
74
+ } , [ enabled , isZoomOut , resetZoomLevel , setZoomLevel ] ) ;
43
75
}
0 commit comments