Modal in React ( Declarative Modal ) (2)

如何从 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,谈我从她们身上学到什麽


<<:  出生第30天 得到快乐的电动挤奶器与仙女们的聚会

>>:  Day26 laravel mail 登入系统 忘记密码

Day 0x13 UVa299 Train Swapping

Virtual Judge ZeroJudge 题意 输入火车的排列状态,输出需要交换多少次以排好...

CISSP答题的思考重点

1.人员 > 流程 > 技术。人身安全永远排在第一顺位,是资安的黄金铁则! 2.组织所有...

Day01-为什麽我要学Vue/Vue简介

我的梦想就是带这一台笔电走遍全世界,「成为一个工程师似乎可以完成这个梦想」,於是在去年底毅然决然的投...

Day 28 : C语言 - 如何解决用scanf连续输入时,程序会自动断行的问题?

如标题,scanf是一个「动态输入」的函数,你可以先宣告一个变数a,再用scanf输入,赋予它任意值...

Day 5 基本型别 - part 2

今天要介绍其他的型别,是原本的 JavaScript 没有的,分别是 Tuple、Enum、Any、...