You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Modal组件无法在Storybook中显示的技术问询

Fixing React Portal Modal Not Showing in Storybook

Let's break down why your Modal isn't rendering correctly in Storybook and fix each issue step by step:

1. The Root Problem: Early DOM Element Query

In your Modal component, you're querying for the #modal container at the module top level:

const modal = document.getElementById('modal') 

When your component module loads (before Storybook renders the decorator that creates the #modal div), this returns null. You create a new div but never actually append it to the #modal container—so the portal has nowhere to mount.

Fix the Portal Mount Logic

Rewrite your Modal component to handle the portal container dynamically with React hooks, ensuring we only interact with the DOM after it exists:

import { useEffect, useRef } from 'react';
import ReactDOM from 'react-dom';

const Modal = ({ open, onClose, children, position }) => {
  // Create a ref for our portal container div
  const portalContainerRef = useRef(document.createElement('div'));

  useEffect(() => {
    // Get the #modal container AFTER the component mounts
    const modalRoot = document.getElementById('modal');
    if (modalRoot) {
      // Append our portal container to the root
      modalRoot.appendChild(portalContainerRef.current);
    }

    // Clean up: remove the container when the component unmounts
    return () => {
      if (modalRoot) {
        modalRoot.removeChild(portalContainerRef.current);
      }
    };
  }, []);

  // Don't render anything if the modal isn't open
  if (!open) return null;

  return ReactDOM.createPortal(
    <>
      <Backdrop onClick={onClose}>
        <ModalBox>
          <Wrapper position={position}>
            {children}
            {/* Add onClick to CloseIcon to trigger onClose */}
            <CloseIcon icon={faTimesCircle} onClick={onClose} />
          </Wrapper>
        </ModalBox>
      </Backdrop>
    </>,
    portalContainerRef.current // Use our ref'd container for the portal
  );
};

2. Storybook State & Interaction Issues

Your Storybook story has two missing pieces that break the user experience:

  • The "Show Modal" button doesn't have a click handler to open the modal
  • You're using the boolean knob directly without tying it to component state (so toggling the knob won't update the modal's open state properly)

Fix the Storybook Story

Update your story to manage state with useState and wire up the button interaction:

import { storiesOf } from '@storybook/react';
import { withKnobs, boolean } from '@storybook/addon-knobs';
import { useState } from 'react';
import Modal from './Modal';

storiesOf('Modals', module)
  .addDecorator(storyFn => (
    // Simplify the decorator—we just need the #modal container
    <div id="modal">
      {storyFn()}
    </div>
  ))
  .addDecorator(withKnobs)
  .add('Modals - Basic', () => {
    // Sync knob value with local state for proper reactivity
    const initialOpen = boolean('open', false);
    const [open, setOpen] = useState(initialOpen);

    return (
      <>
        <button type="button" onClick={() => setOpen(true)}>Show Modal</button>
        <Modal 
          open={open} 
          onClose={() => setOpen(false)} // Pass onClose to update state
        >
          <Modal.Header>Modal Header goes here</Modal.Header>
          <Modal.Content>Modal Content goes here</Modal.Content>
          <Modal.Footer>Modal Footer goes here</Modal.Footer>
        </Modal>
      </>
    );
  });

3. Bonus: Fix Close Icon Interaction

Notice in the updated Modal component we added onClick={onClose} to the CloseIcon—your original code didn't bind this event, so clicking the close icon wouldn't have closed the modal anyway.

After applying these fixes, your modal should render correctly in Storybook: clicking the button will open it, clicking the backdrop or close icon will close it, and the knob will let you toggle the initial open state.

内容的提问来源于stack exchange,提问作者milan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:35:18