首页 > 解决方案 > 如何从 React 自定义钩子和控制它的函数中正确导出组件?

问题描述

我想做的是创建一种可重用且方便的方式来显示警报或确认模式。

使用库模态通常需要您导入一个模态组件并创建一个状态变量并将其作为道具传递给导入的组件以控制其可见性。我想要做的是创建一个自定义钩子,它导出一个具有所有自定义项的模态组件(可能是库中模态组件的包装器)和一个切换可见性的函数。像下面的东西。这是钩子代码:

import React, {useState} from 'react'
import 'antd/dist/antd.css'
import {Modal as AntdModal} from 'antd'

const useModal = () => {
  const [on, setOn] = useState(false)
  const toggleModal = () => setOn(!on)
  const Modal = ({onOK, ...rest}) => (
    <AntdModal
      {...rest}
      visible={on}
      onOk={() => {
        onOK && onOK()
        toggleModal()
      }}
      onCancel={toggleModal}
    />
  )
  return {
    on,
    toggleModal,
    Modal,
  }
}

export default useModal

这就是我使用它的方式:

import React, {useState} from 'react'
import ReactDOM from 'react-dom'
import useModal from './useModal'
import {Button} from 'antd'

const App = () => {
  const {toggleModal, Modal} = useModal()

  return (
    <div>
      <Button type="primary" onClick={toggleModal}>
        Open Modal
      </Button>

      <Modal title="Simple" onOK={() => alert('Something is not OK :(')}>
        <p>Modal content...</p>
      </Modal>
    </div>
  )
}

const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)

这是一个沙箱,可以查看它的运行情况并进行测试。有两个按钮,一个显示通常从库(此处为 antd)导入的 Modal,另一个显示自定义钩子useModal

钩子工作的一种形式,除了它似乎有问题。出现的过渡正在工作,但是当您关闭模式时,它突然消失而没有过渡。似乎该组件在过渡之前立即被销毁。我究竟做错了什么?

标签: reactjsreact-hooks

解决方案


如果我理解正确,您想要渲染一个组件并且还需要一个可以控制它的函数(切换它的可见性)。

react hooks尽管您尝试Modal使用Dialogue.

您可以使用以下解决方案来实现相同的结果。该解决方案使用一个组件,forwardRef并且useImperativeHandle将实现一个解耦功能,您可以使用该功能通过单击按钮来切换对话:

注意:您需要升级到react最新版本(如您react-domv-16.7.0-alpha沙盒代码)到最新版本(16.14.0)[我没有尝试过其他中间版本]

模态组件:

import React, {useState, forwardRef, useImperativeHandle} from 'react'
import 'antd/dist/antd.css'
import {Modal as AntdModal} from 'antd'

const Modal = forwardRef(({onOK, ...rest}, ref) => {
  useImperativeHandle(ref, () => ({
    toggleModal: toggleModal
  }));

  const [on, setOn] = useState(false)
  const toggleModal = () => setOn(!on)

  return (
    <AntdModal
      {...rest}
      visible={on}
      onOk={() => {
        onOK && onOK()
        toggleModal()
      }}
      onCancel={toggleModal}
    />
  )
});

export default Modal;

这是如何使用它:

import React, {useState, useRef} from 'react'
import ReactDOM from 'react-dom'
import Modal from './ModalWrapper'

import {Button, Modal as AntdModal} from 'antd'

const App = () => {
  const [on, setOn] = useState(false)
  const toggle = () => setOn(!on)

  const modalRef = useRef()
  return (
    <div>
      <Button type="warning" onClick={() => setOn(true)}>
        Normal Import
      </Button>
      <br />
      <br />
      <Button type="primary" onClick={() => modalRef.current.toggleModal()}>
        From Modal Component
      </Button>

      <AntdModal visible={on} onOk={toggle} onCancel={toggle}>
        <p>I was imported directly...</p>
        <p>I was imported directly...</p>
        <p>I was imported directly...</p>
      </AntdModal>

      <Modal
        title="Simple"
        ref={modalRef}
        onOK={() => alert('Things are now OK :)')}
      >
        <p>I was imported from Modal Component...</p>
        <p>I was imported from Modal Component...</p>
        <p>I was imported from Modal Component...</p>
      </Modal>
    </div>
  )
}

const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)

我希望它会对您的用例有所帮助。

谢谢。


推荐阅读