DEV Community

longchun
longchun

Posted on

Refactoring React Modals: From Imperative Handles to Declarative Props for Cleaner Code

𝐅ðŦðĻðĶ 𝐈ðĶðĐ𝐞ðŦ𝐚𝐭ðĒðŊ𝐞 𝐇𝐚𝐧𝐝ðĨ𝐞𝐎 𝐭ðĻ 𝐃𝐞𝐜ðĨ𝐚ðŦ𝐚𝐭ðĒðŊ𝐞 𝐏ðŦðĻðĐ𝐎 𝐟ðĻðŦ 𝐂ðĨ𝐞𝐚𝐧𝐞ðŦ 𝐂ðĻ𝐝𝐞

𝖎𝖚𝗇𝖚𝗀𝗂𝗇𝗀 ð—†ð—ˆð–―ð–šð—… 𝗏𝗂𝗌𝗂ð–ŧ𝗂𝗅𝗂𝗍𝗒 𝗂𝗇 ð–ąð–ū𝖚𝖞𝗍 𝖞𝗈𝗆𝗉𝗈𝗇ð–ū𝗇𝗍𝗌 𝗂𝗌 𝖚 𝖞𝗈𝗆𝗆𝗈𝗇 𝗍𝖚𝗌𝗄.
ð–ķ𝗁𝗂𝗅ð–ū 𝗎𝗌ð–ūð–Ļ𝗆𝗉ð–ū𝗋𝖚𝗍𝗂𝗏ð–ūð–§ð–šð—‡ð–―ð—…ð–ū 𝖞𝗈𝗆ð–ŧ𝗂𝗇ð–ūð–― 𝗐𝗂𝗍𝗁 ð–ŋð—ˆð—‹ð—ð–šð—‹ð–―ð–ąð–ūð–ŋ 𝗈ð–ŋð–ŋð–ū𝗋𝗌 𝖚 𝗉𝗈𝗐ð–ū𝗋ð–ŋ𝗎𝗅 𝗐𝖚𝗒 𝗍𝗈 ð–ū𝗑𝗉𝗈𝗌ð–ū 𝗆ð–ūð—ð—ð—ˆð–―ð—Œ ð–ŋ𝗋𝗈𝗆 𝖚 ð–žð—ð—‚ð—…ð–― 𝖞𝗈𝗆𝗉𝗈𝗇ð–ū𝗇𝗍 𝗍𝗈 𝗂𝗍𝗌 𝗉𝖚𝗋ð–ū𝗇𝗍, 𝗂𝗍 𝗈ð–ŋ𝗍ð–ū𝗇 ð—‚ð—‡ð—ð—‹ð—ˆð–―ð—Žð–žð–ū𝗌 𝖚𝗇 𝗂𝗆𝗉ð–ū𝗋𝖚𝗍𝗂𝗏ð–ū 𝖞𝗈𝗇𝗍𝗋𝗈𝗅 ð–ŋ𝗅𝗈𝗐 𝗍𝗁𝖚𝗍 𝖞𝖚𝗇 ð–ŧð–ū 𝗅ð–ū𝗌𝗌 𝗂𝗇𝗍𝗎𝗂𝗍𝗂𝗏ð–ū 𝗍𝗁𝖚𝗇 ð–ąð–ū𝖚𝖞𝗍'𝗌 ð–―ð–ū𝖞𝗅𝖚𝗋𝖚𝗍𝗂𝗏ð–ū ð—‰ð–šð—‹ð–šð–―ð—‚ð—€ð—†.

𝐈ðĶðĐ𝐞ðŦ𝐚𝐭ðĒðŊ𝐞 𝐂ðĻ𝐧𝐭ðŦðĻðĨ 𝐰ðĒð­ðĄ 𝚞ĖēĖē𝚜ĖēĖē𝚎ĖēĖēð™ļĖēĖē𝚖ĖēĖē𝚙ĖēĖē𝚎ĖēĖē𝚛ĖēĖē𝚊ĖēĖē𝚝ĖēĖē𝚒ĖēĖē𝚟ĖēĖē𝚎ĖēĖē𝙷ĖēĖē𝚊ĖēĖē𝚗ĖēĖē𝚍ĖēĖē𝚕ĖēĖē𝚎Ėē

The initial pattern uses Ėē𝚏ĖēĖē𝚘ĖēĖē𝚛ĖēĖē𝚠ĖēĖē𝚊ĖēĖē𝚛ĖēĖē𝚍ĖēĖē𝚁ĖēĖē𝚎ĖēĖē𝚏Ėē to pass a ref down to the ResultModal component. Inside the component, 𝚞ĖēĖē𝚜ĖēĖē𝚎ĖēĖēð™ļĖēĖē𝚖ĖēĖē𝚙ĖēĖē𝚎ĖēĖē𝚛ĖēĖē𝚊ĖēĖē𝚝ĖēĖē𝚒ĖēĖē𝚟ĖēĖē𝚎ĖēĖē𝙷ĖēĖē𝚊ĖēĖē𝚗ĖēĖē𝚍ĖēĖē𝚕ĖēĖē𝚎Ėē then allows us to define specific methods (like Ėē𝚘ĖēĖē𝚙ĖēĖē𝚎ĖēĖē𝚗Ėē() and Ėē𝚌ĖēĖē𝚕ĖēĖē𝚘ĖēĖē𝚜ĖēĖē𝚎Ėē()) that can be called directly from the parent via that Ėē𝚛ĖēĖē𝚎ĖēĖē𝚏Ėē.

// Parent component would call:
// modalRef.current.open();
// modalRef.current.close();
Enter fullscreen mode Exit fullscreen mode

𝐃𝐞𝐜ðĨ𝐚ðŦ𝐚𝐭ðĒðŊ𝐞 𝐂ðĻ𝐧𝐭ðŦðĻðĨ 𝐰ðĒð­ðĄ 𝐏ðŦðĻðĐ𝐎

ð–Ĩ𝗈𝗋 𝗌𝗂𝗆𝗉𝗅ð–ū 𝗌𝗁𝗈𝗐/ð—ð—‚ð–―ð–ū ð–ŋ𝗎𝗇𝖞𝗍𝗂𝗈𝗇𝖚𝗅𝗂𝗍𝗒, 𝖚 𝗆𝗈𝗋ð–ū 'ð–ąð–ū𝖚𝖞𝗍-𝗒' 𝗐𝖚𝗒 𝗂𝗌 𝗍𝗈 𝖞𝗈𝗇𝗍𝗋𝗈𝗅 𝗍𝗁ð–ū ð—†ð—ˆð–―ð–šð—…'𝗌 𝗏𝗂𝗌𝗂ð–ŧ𝗂𝗅𝗂𝗍𝗒 𝗍𝗁𝗋𝗈𝗎𝗀𝗁 𝗉𝗋𝗈𝗉𝗌. ð–ķð–ū ð—‚ð—‡ð—ð—‹ð—ˆð–―ð—Žð–žð–ū 𝖚𝗇 𝚒Ėē𝗌ð–Ū𝗉ð–ū𝗇 𝗉𝗋𝗈𝗉 𝗍𝗈 ð–―ð—‚ð–žð—ð–šð—ð–ū 𝗐𝗁ð–ū𝗍𝗁ð–ū𝗋 𝗍𝗁ð–ū ð—†ð—ˆð–―ð–šð—… ð—Œð—ð—ˆð—Žð—…ð–― ð–ŧð–ū 𝗈𝗉ð–ū𝗇 𝗈𝗋 𝖞𝗅𝗈𝗌ð–ūð–―, ð–šð—‡ð–― 𝖚𝗇 𝗈𝗇ð–Ē𝗅𝗈𝗌ð–ū 𝗉𝗋𝗈𝗉 𝗍𝗈 ð—ð–šð—‡ð–―ð—…ð–ū 𝗍𝗁ð–ū 𝖞𝗅𝗈𝗌𝗂𝗇𝗀 ð–ū𝗏ð–ū𝗇𝗍 ð–ŋ𝗋𝗈𝗆 𝗐𝗂𝗍𝗁𝗂𝗇 𝗍𝗁ð–ū ð—†ð—ˆð–―ð–šð—….

import { useRef, useEffect } from "react";

export default function ResultModal({ result, targetTime, isOpen, onClose }) {
  const dialogRef = useRef();

  // Crucially, we use useEffect to synchronize the modal's state
  // with the `isOpen` prop.
  useEffect(() => {
    if (isOpen) {
      // The HTML <dialog> element's showModal() method opens the modal
      // in a top-layer, blocking state.
      dialogRef.current?.showModal();
    } else {
      // The close() method dismisses the modal.
      dialogRef.current?.close();
    }
  }, [isOpen]); // Dependency array: This effect runs ONLY when `isOpen` changes.

  return (
    <dialog ref={dialogRef} className="result-modal" onClose={onClose}>
      <h2>You {result}</h2>
      <p>The target time was <strong>{targetTime} seconds.</strong></p>
      <p>You stopped the timer with <strong>X seconds left.</strong></p>
      <form method="dialog">
        <button onClick={onClose}>Close</button>
      </form>
    </dialog>
  );
}
Enter fullscreen mode Exit fullscreen mode

𝐏ðŦðĻðĐ-𝐁𝐚𝐎𝐞𝐝 𝐀ðĐðĐðŦðĻðšðœðĄ:

  1. 𝘋ð˜Ķð˜Ī𝘭ð˜Ēð˜ģð˜Ēð˜ĩ𝘊𝘷ð˜Ķ 𝘊𝘰ð˜Ŋð˜ĩð˜ģ𝘰𝘭: ð–ģ𝗁ð–ū 𝗉𝖚𝗋ð–ū𝗇𝗍 𝖞𝗈𝗆𝗉𝗈𝗇ð–ū𝗇𝗍 ð–―ð–ū𝖞𝗅𝖚𝗋ð–ū𝗌 𝗍𝗁ð–ū ð–―ð–ū𝗌𝗂𝗋ð–ūð–― 𝗌𝗍𝖚𝗍ð–ū (𝗂𝗌ð–Ū𝗉ð–ū𝗇: 𝗍𝗋𝗎ð–ū 𝗈𝗋 𝗂𝗌ð–Ū𝗉ð–ū𝗇: ð–ŋ𝖚𝗅𝗌ð–ū
  2. 𝘌ð˜đð˜ąð˜­ð˜Šð˜Ī𝘊ð˜ĩ 𝘋ð˜Ēð˜ĩð˜Ē 𝘍𝘭𝘰ð˜ļ: ð–ģ𝗁ð–ū ð–ŋ𝗅𝗈𝗐 𝗈ð–ŋ ð–―ð–šð—ð–š 𝗂𝗌 𝖞𝗅ð–ū𝖚𝗋: 𝚒ĖēĖē𝚜ĖēĖēð™ūĖēĖē𝚙ĖēĖē𝚎ĖēĖē𝚗Ėē ð–šð—‡ð–― 𝚘ĖēĖē𝚗ĖēĖēð™ēĖēĖē𝚕ĖēĖē𝚘ĖēĖē𝚜ĖēĖē𝚎Ėē 𝖚𝗋ð–ū ð–ū𝗑𝗉𝗅𝗂𝖞𝗂𝗍𝗅𝗒 𝗉𝖚𝗌𝗌ð–ūð–― ð–―ð—ˆð—ð—‡ 𝖚𝗌 𝗉𝗋𝗈𝗉𝗌.
  3. 𝘚𝘚ð˜Ŋð˜Īð˜Đð˜ģ𝘰ð˜Ŋ𝘊ð˜ŧð˜Ēð˜ĩ𝘊𝘰ð˜Ŋ ð˜ļ𝘊ð˜ĩð˜Đ ð˜ķð˜īð˜Ķ𝘌𝘧𝘧ð˜Ķð˜Īð˜ĩ: ð–ģ𝗁ð–ū 𝗎𝗌ð–ūð–Īð–ŋð–ŋð–ū𝖞𝗍 𝗁𝗈𝗈𝗄 𝗂𝗌 𝗏𝗂𝗍𝖚𝗅 𝗁ð–ū𝗋ð–ū. ð–Ļ𝗍 ð–ū𝗇𝗌𝗎𝗋ð–ū𝗌 𝗍𝗁𝖚𝗍 𝗍𝗁ð–ū 𝚜ĖēĖē𝚑ĖēĖē𝚘ĖēĖē𝚠ĖēĖē𝙞ĖēĖē𝚘ĖēĖē𝚍ĖēĖē𝚊ĖēĖē𝚕Ėē() 𝗈𝗋 𝚌ĖēĖē𝚕ĖēĖē𝚘ĖēĖē𝚜ĖēĖē𝚎Ėē() 𝗆ð–ūð—ð—ð—ˆð–―ð—Œ 𝗈ð–ŋ 𝗍𝗁ð–ū 𝗇𝖚𝗍𝗂𝗏ð–ū 𝖧ð–ģ𝖎ð–Ŧ <Ėē𝚍ĖēĖē𝚒ĖēĖē𝚊ĖēĖē𝚕ĖēĖē𝚘ĖēĖē𝚐Ėē>
  4. 𝘓ð˜Ķ𝘷ð˜Ķð˜ģð˜Ēð˜Ļ𝘊ð˜Ŋð˜Ļ 𝘕ð˜Ēð˜ĩ𝘊𝘷ð˜Ķ <ð˜Ĩ𝘊ð˜Ē𝘭𝘰ð˜Ļ>: This approach effectively uses the built-in functionality of the HTML <Ėē𝚍ĖēĖē𝚒ĖēĖē𝚊ĖēĖē𝚕ĖēĖē𝚘ĖēĖē𝚐Ėē> element.

ð–ķ𝗁𝗂𝗅ð–ū 𝚞ĖēĖē𝚜ĖēĖē𝚎ĖēĖēð™ļĖēĖē𝚖ĖēĖē𝚙ĖēĖē𝚎ĖēĖē𝚛ĖēĖē𝚊ĖēĖē𝚝ĖēĖē𝚒ĖēĖē𝚟ĖēĖē𝚎ĖēĖē𝙷ĖēĖē𝚊ĖēĖē𝚗ĖēĖē𝚍ĖēĖē𝚕ĖēĖē𝚎Ėē 𝗁𝖚𝗌 𝗂𝗍𝗌 𝗅ð–ū𝗀𝗂𝗍𝗂𝗆𝖚𝗍ð–ū 𝗎𝗌ð–ū 𝖞𝖚𝗌ð–ū𝗌 (ð–ū.𝗀., ð–ū𝗑𝗉𝗈𝗌𝗂𝗇𝗀 𝖚𝗇 𝖠ð–Ŋð–Ļ ð–ŋ𝗈𝗋 ð–ŋ𝗈𝖞𝗎𝗌𝗂𝗇𝗀 ð–ū𝗅ð–ū𝗆ð–ū𝗇𝗍𝗌, 𝗍𝗋𝗂𝗀𝗀ð–ū𝗋𝗂𝗇𝗀 𝖚𝗇𝗂𝗆𝖚𝗍𝗂𝗈𝗇𝗌), ð–ŋ𝗈𝗋 𝗌𝗂𝗆𝗉𝗅ð–ū 𝗌𝗍𝖚𝗍ð–ū-ð–―ð—‹ð—‚ð—ð–ū𝗇 𝗂𝗇𝗍ð–ū𝗋𝖚𝖞𝗍𝗂𝗈𝗇𝗌 𝗅𝗂𝗄ð–ū 𝗌𝗁𝗈𝗐𝗂𝗇𝗀/ð—ð—‚ð–―ð—‚ð—‡ð—€ 𝖚 ð—†ð—ˆð–―ð–šð—…, 𝖚 𝗉𝗋𝗈𝗉-ð–ŧ𝖚𝗌ð–ūð–― 𝖚𝗉𝗉𝗋𝗈𝖚𝖞𝗁 𝗈ð–ŋ𝗍ð–ū𝗇 𝗅ð–ūð–šð–―ð—Œ 𝗍𝗈 𝗆𝗈𝗋ð–ū 𝗋ð–ūð–šð–―ð–šð–ŧ𝗅ð–ū, 𝗆𝖚𝗂𝗇𝗍𝖚𝗂𝗇𝖚ð–ŧ𝗅ð–ū, ð–šð—‡ð–― 𝗉𝗋ð–ūð–―ð—‚ð–žð—ð–šð–ŧ𝗅ð–ū ð–ąð–ū𝖚𝖞𝗍 𝖞𝗈𝗆𝗉𝗈𝗇ð–ū𝗇𝗍𝗌.

ð–ķ𝗁𝖚𝗍 𝖚𝗋ð–ū 𝗒𝗈𝗎𝗋 𝗍𝗁𝗈𝗎𝗀𝗁𝗍𝗌 𝗈𝗇 𝗂𝗆𝗉ð–ū𝗋𝖚𝗍𝗂𝗏ð–ū 𝗏𝗌. ð–―ð–ū𝖞𝗅𝖚𝗋𝖚𝗍𝗂𝗏ð–ū 𝗉𝖚𝗍𝗍ð–ū𝗋𝗇𝗌 𝗂𝗇 ð–ąð–ū𝖚𝖞𝗍? ð–ē𝗁𝖚𝗋ð–ū 𝗒𝗈𝗎𝗋 𝗂𝗇𝗌𝗂𝗀𝗁𝗍𝗌!

React #FrontendDevelopment #JavaScript #WebDevelopment #CleanCode #ReactHooks"

Top comments (0)