Преглед изворни кода

fix modal island ref init (#2341)

* fix modal island ref init

* remove unnecessary sIP

* naming
David Luzar пре 4 година
родитељ
комит
56938cf874
1 измењених фајлова са 22 додато и 17 уклоњено
  1. 22 17
      src/components/Dialog.tsx

+ 22 - 17
src/components/Dialog.tsx

@@ -1,4 +1,4 @@
-import React, { useEffect, useRef } from "react";
+import React, { useCallback, useEffect, useState } from "react";
 import clsx from "clsx";
 import { Modal } from "./Modal";
 import { Island } from "./Island";
@@ -9,6 +9,14 @@ import { KEYS } from "../keys";
 
 import "./Dialog.scss";
 
+const useRefState = <T,>() => {
+  const [refValue, setRefValue] = useState<T | null>(null);
+  const refCallback = useCallback((value: T) => {
+    setRefValue(value);
+  }, []);
+  return [refValue, refCallback] as const;
+};
+
 export const Dialog = (props: {
   children: React.ReactNode;
   className?: string;
@@ -16,25 +24,23 @@ export const Dialog = (props: {
   onCloseRequest(): void;
   title: React.ReactNode;
 }) => {
-  const islandRef = useRef<HTMLDivElement>(null);
+  const [islandNode, setIslandNode] = useRefState<HTMLDivElement>();
 
   useEffect(() => {
-    const focusableElements = queryFocusableElements();
+    if (!islandNode) {
+      return;
+    }
+
+    const focusableElements = queryFocusableElements(islandNode);
 
     if (focusableElements.length > 0) {
       // If there's an element other than close, focus it.
       (focusableElements[1] || focusableElements[0]).focus();
     }
-  }, []);
-
-  useEffect(() => {
-    if (!islandRef.current) {
-      return;
-    }
 
     const handleKeyDown = (event: KeyboardEvent) => {
       if (event.key === KEYS.TAB) {
-        const focusableElements = queryFocusableElements();
+        const focusableElements = queryFocusableElements(islandNode);
         const { activeElement } = document;
         const currentIndex = focusableElements.findIndex(
           (element) => element === activeElement,
@@ -53,14 +59,13 @@ export const Dialog = (props: {
       }
     };
 
-    const node = islandRef.current;
-    node.addEventListener("keydown", handleKeyDown);
+    islandNode.addEventListener("keydown", handleKeyDown);
 
-    return () => node.removeEventListener("keydown", handleKeyDown);
-  }, []);
+    return () => islandNode.removeEventListener("keydown", handleKeyDown);
+  }, [islandNode]);
 
-  const queryFocusableElements = () => {
-    const focusableElements = islandRef.current?.querySelectorAll<HTMLElement>(
+  const queryFocusableElements = (node: HTMLElement) => {
+    const focusableElements = node.querySelectorAll<HTMLElement>(
       "button, a, input, select, textarea, div[tabindex]",
     );
 
@@ -74,7 +79,7 @@ export const Dialog = (props: {
       maxWidth={props.maxWidth}
       onCloseRequest={props.onCloseRequest}
     >
-      <Island padding={4} ref={islandRef}>
+      <Island padding={4} ref={setIslandNode}>
         <h2 id="dialog-title" className="Dialog__title">
           <span className="Dialog__titleContent">{props.title}</span>
           <button