React hooks最激动人心的部分无疑是自定义hook,充满了无限的可能和可复用性,同时让代码史无前例得清晰。css
# 建立项目
create-react-app myApp
# 进入项目目录
cd myApp
# 升级 react 和 react-dom
yarn add react@next react-dom@next
复制代码
便可。html
今天写了一个奇异的custom hooks,奇异之处在于返回了组件。react
一个普通的 antd
的 Modal
用例以下:
官网连接antd
import { Modal, Button } from 'antd';
class App extends React.Component {
state = { visible: false }
showModal = () => {
this.setState({
visible: true,
});
}
handleOk = (e) => {
console.log(e);
this.setState({
visible: false,
});
}
handleCancel = (e) => {
console.log(e);
this.setState({
visible: false,
});
}
render() {
return (
<div> <Button type="primary" onClick={this.showModal}> Open Modal </Button> <Modal title="Basic Modal" visible={this.state.visible} onOk={this.handleOk} onCancel={this.handleCancel} > <p>Some contents...</p> <p>Some contents...</p> <p>Some contents...</p> </Modal> </div>
);
}
}
ReactDOM.render(<App />, mountNode); 复制代码
会不会以为好烦? 我就想用一下弹层,怎么又要定义 visible 的 state,又要写 showModal 方法。app
<Button type="primary" onClick={this.showModal}>
Open Modal
</Button>
<Modal title="Basic Modal" visible={this.state.visible} onOk={this.handleOk} onCancel={this.handleCancel} >
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</Modal>
复制代码
可否简化成dom
<Button type="primary">
Open Modal
</Button>
<Modal title="Basic Modal" onOk={this.handleOk} >
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</Modal>
复制代码
呢?能够。性能
因而我写了这个demo:Code Demoui
const App = () => {
const {MyBtn, MyModal} = useModal()
return (
<div> <MyBtn type="primary">Click me!</MyBtn> <MyModal title="Basic Modal" onOK={() => alert('everything is OK')}> <p>Some contents...</p> <p>Some contents...</p> <p>Some contents...</p> </MyModal> </div>
)
}
复制代码
这里的 useModal
是一个 custom hooks。实现代码是this
import React, {useState} from 'react'
import 'antd/dist/antd.css'
import {Button, Modal} from 'antd'
const useModal = () => {
const [on, setOn] = useState(false)
const toggle = () => setOn(!on)
const MyBtn = props => <Button {...props} onClick={toggle} />
const MyModal = ({onOK, ...rest}) => (
<Modal {...rest} visible={on} onOk={() => { onOK && onOK() toggle() }} onCancel={toggle} /> ) return { on, toggle, MyBtn, MyModal, } } 复制代码
对于使用者甚至不用关心具体实现,直接把 Button 和 Modal 拿来用就好,点击 Button 就会弹 Modal,什么 visible,toggle,onClick 等只和 Modal 内部实现相关的逻辑全全隐藏了。spa
你们怎么看?
补充:一直以为这么写有点性能问题,在reddit上问了下,Dan 给出的回复以下:
The problem with this code is that it returns a new component type on every render. This means that the >state of all components below Modal will be reset because
OldModal !== NewModal
on every next render. >You can learn more about it here: reactjs.org/docs/reconc…Instead, you can return elements directly. But don't return components.
简单的说,返回 Modal 组件,因为React内部diff的断定方式,会认为任何两次渲染中 type 都不一样,因此会使得 Modal 的全部子树每次都丢弃并从新渲染。这不得不说是一个性能问题。因此暂时不推荐用此 hook。