iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 26
0
Modern Web

關於React,那些我不知道的系列 第 26

Modal in React ( Declarative Modal ) (2)

  • 分享至 

  • xImage
  •  

如何從 Modal 外部帶入元件給內部渲染?

續前篇提出的疑問 Modal in React ( React 當中的互動視窗、對畫框) : 如何從外部帶入元件?

Show me the code: Codesandbox Demo

以下範例

function BootstrapModalExample() {
  const [show, setShow] = useState(false);
  const handleClose = () => setShow(false);
  const handleShow = () => setShow(true);

  return (
    <>
      <Button variant="primary" onClick={handleShow}>
        Launch demo modal
      </Button>
      {/* Modal */}
      <Modal show={show} onHide={handleClose}>
        {/* 裡面是Modal元件內其他東西,這邊先忽略 */}
      </Modal>
    </>
  );
}

Step1 把元件改成用 props 帶入

   <BootstrapModalExample
        component={<Button variant="primary">Launch demo modal</Button>}
     />
function BootstrapModalExample({ component }) {
  const [show, setShow] = useState(false);
  const handleClose = () => setShow(false);
  const handleShow = () => setShow(true);

  return (
    <>
      {component}
      {/* <Button variant="primary" onClick={handleShow}>
         Launch demo modal
      </Button> */}
      {/* Modal */}
      <Modal show={show} onHide={handleClose}>
        {/* 裡面是Modal元件內其他東西,這邊先忽略 */}
      </Modal>
    </>
  );
}

發現我們沒辦法將 handleShow (onClick handler) 這個 callback 放進去。

這時我們遇到一個問題,我們該如何把 子元件 的狀態 丟給 父元件 使用?

Step2 改採用 render props

這代表我們想要將 Children 進行一段加工,然後在渲染,這時我們想到可以使用 render props 的技巧。定義一個 function 作為 props 。 並在這 function 當中把 handleShow 作為input,然後output出展示元件,且在該元件帶入 handleShow

    <>
      {renderTrigger && renderTrigger( handleShow )}
      {/* component */}
      {/* <Button variant="primary" onClick={handleShow}>
         Launch demo modal
      </Button> */}
      {/* Modal */}
      <Modal show={show} onHide={handleClose}>
        {/* 裡面是Modal元件內其他東西,這邊先忽略 */}
      </Modal>
    </>

如此我們便能在父層使用

      <BootstrapModalExample
        renderTrigger={(handleShow) => (
          <Button variant="primary" onClick={handleShow}>
            Launch demo modal
          </Button>
        )}
      />
      <BootstrapModalExample
        renderTrigger={(handleShow) => (
          <img onClick={handleShow} src={`https://loremflickr.com/200/200`} />
        )}
      />

step3 細部優化

1. 防止 App Crash

為避免我們 呼叫 <BootstrapModalExample/> 這個元件時,忘記帶入 props 導致我們的 App Crash,我們可在 renderTrigger( handleShow ) 之前加入一組短路: renderTrigger && renderTrigger( handleShow ) 。 使我們就算忘記帶入props 不至於導致 App crash ( 只不過此時也什麼都不會出現XDD )

    <>
      {renderTrigger && renderTrigger( handleShow )}
      {/* Modal */}
      <Modal show={show} onHide={handleClose}>
        {/* 裡面是Modal元件內其他東西,這邊先忽略 */}
      </Modal>
    </>

2. 增加元件使用彈性

使我們的 render props 更彈性,假如我們不只想要帶入 handleShow ,還想帶入更多東西的話。
我們將 renderTrigger 這個 function 改吃 一個物件,這樣執行 function 時,需要帶入的 input 成為一個物件,在這個物件當中,我們就可以放入其他需要的東西了。

    <>
      {renderTrigger && renderTrigger( { handleShow, loading, someOtherYouNeed } )}
      {/* Modal */}
      <Modal show={show} onHide={handleClose}>
        {/* 裡面是Modal元件內其他東西,這邊先忽略 */}
      </Modal>
    </>

Codesandbox Demo

參考資料

React 官網 render props
如何寫一個最簡單的 Render Props?
HOC 與Render Props,談我從她們身上學到什麼


上一篇
Modal in React ( React 當中的互動視窗、對畫框)
下一篇
不用Recoil的話,如何自己製作一個 Custom hook 來共享全域變數?
系列文
關於React,那些我不知道的30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言