一個hooks的「奇異」用法

React hooks最激動人心的部分無疑是自定義hook,充滿了無限的可能和可複用性,同時讓代碼史無前例得清晰。css

  • 如何如今就使用hooks?
# 建立項目
create-react-app myApp
# 進入項目目錄
cd myApp
# 升級 react 和 react-dom
yarn add react@next react-dom@next
複製代碼

便可。html

今天寫了一個奇異的custom hooks,奇異之處在於返回了組件。react

一個普通的 antdModal 用例以下:
官網連接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。

相關文章
相關標籤/搜索