[譯] 使用 Recompose 來構建高階組件

2020-05-01-MqJX_8EaStM

使用 Recompose 來構建高階組件

Workpop 公司,咱們不斷使用不一樣的組件設計模式來迭代咱們的產品,以適應瞬息萬變的 React 生態系統。早些時候,咱們從試用高階組件設計模式(HOC)中嚐到一點甜頭。前端

什麼是高階組件?

高階組件只是一個函數,只不過它返回的是用來渲染 React 組件的函數。android

這裏有個例子:ios

import { Component } from 'React';

export function enhancer() {
 return (BaseComponent) => {
   return class extends Component {
     constructor() {
        this.state = { visible: false }; 
     }
     componentDidMount() {
        this.setState({ visible: true });
     }
     render() {
       return <BaseComponent {...this.props} {...this.state} />;
     }
   }  
 };
}

正如你看到的這個例子,咱們只有一個給你的組件提供功能的函數。在本例中,咱們添加了一些 state 來控制可見性。git

咱們能夠看看它的使用方式:github

// 展現型組件

function Sample({ visible }) {
 return visible ? <div> I am Visible </div> : <div> I am not Visible </div>
}

export default enhance()(Sample);

高階組件模式的意義何在?

當構建組件時,我強烈建議將展現型組件和加強型組件(高階組件)進行分離。我喜歡使用術語加強型組件來描述高階組件,是由於這個詞從字面上可讓咱們更好的理解它的用途。後端

加強型組件的用途:設計模式

  • 能夠給其餘的展現型組件進行相同的代碼複用;
  • 簡化可讀性較差的臃腫的組件;
  • 能夠控制傳入組件的渲染;
  • 能夠給任何組件增長 state,這意味着你再也不須要依賴 Redux 來託管全部 state(若是你正這樣作);
  • 操做你傳給展現型組件的 props(map,reduce 等任何你喜歡的方法)。

爲何不使用類來實現它呢?

若是你想用 ES6 的類語法來實現也能夠。我我的傾向於使用函數式無狀態的組件來構建應用的 UI。模塊化

function HellWorld({ message = 'Hello World' }) {
  return <h1>{message}</h1>;
}

使用函數式組件的優勢:函數

  • 模塊化代碼 — 能夠在整個項目範圍內複用你的代碼段;
  • 只依賴於 props — 默認沒有 state;
  • 更便於單元測試 — 對測試工具 enzyme/jest 更友好的測試接口;
  • 更便於 Mock 數據 — 能夠對不一樣場景方便的進行數據 Mock。

咱們走過的旅程

而後咱們開始在生產環境中深度使用高階組件了,並在使用過程當中遇到了幾個問題。好比爲簡單的場景不斷地編寫簡單地高階組件就很無聊,沒有將多個高階組件進行合成的方法,也沒法避免開發出冗餘的高階組件(這個最麻煩,但我清楚這有時確實會發生)。人們逐漸陷入高階組件的語法和觀念中步履維艱(正如如今不少工程師的狀態),這種模式彷佛也已漸漸失去了價值。工具

咱們真正須要的解決方案是這樣的:

  • 強制模式
  • 易於組合
  • 易於使用

這就是咱們爲什麼引入 Recompose

開始使用 Recompose

Recompose 是一個爲函數式組件和高階組件開發的 React 工具庫。能夠把它當作 React 的 Lodash。

這正是咱們所須要的。咱們的同事們都喜歡用 Lodash,如今跟他們說開發高階組件將和使用 Lodash 有類似的開發體驗。恩,有戲。

咱們來寫個簡單地 DEMO 看看:

假如咱們有這樣一個組件約束:

  • 須要 state 來控制可見性;
  • 須要將改變可見性的函數放到咱們的組件中;
  • 須要在組件中添加一些 props。

步驟 1 — 編寫展現型組件

export default function Presentation({ title, message, toggleVisibility, isVisible }) {
 return  (
   <div>
     <h1>{title}</h1>
     {isVisible ? <p>I'm visible</p> : <p> Not Visible </p>}
     <p>{message}</p>
     <button onClick={toggleVisibility}> Click me! </button>
   </div> 
 );
}

如今咱們須要去提取這個組件的加強型組件了。

步驟 2 — 編寫容器

我一般會把一些 Recompose 的加強型組件合成在一塊兒,因此這個步驟是創建你的 compose:

import { compose } from 'recompose';

export default compose(
  /*********************************** 
   *
   * 咱們將把加強型組件放在這裏
   *
   ***********************************/
)(Presentation);

什麼是 Recompose 中的 compose?它至關於 Lodash 中的 flowRight 函數。

咱們可使用 compose 來將多個高階組件轉化爲一個高階組件。

步驟 3 — 正確獲取 state

好了,咱們如今須要從這個組件中正確獲取 state

在 Recompose 中,咱們可使用 withState 加強型組件來設置組件內的 state,而且使用 withHandlers 加強型組件來設置組件的事件處理函數。

import { compose, withState, withHandlers } from 'recompose';

export default compose(
  withState('isVisible', 'toggleVis', false),  
  withHandlers({
    toggleVisibility: ({ toggleVis, isVisible }) => {
     return (event) => {
       return toggleVis(!isVisible);
     };
    },
  })
)(Presentation);

這裏咱們設置了一個 isVisiblestate,一個控制可見性的方法 toggleVis,和一個初始值 false。

withHandlers 建立了一個高階組件,它接受一系列 props 並返回一個處理函數,在這個例子中是切換可見性 state 的函數。toggleVisibility 這個函數將做爲 Presentation 組件的一個 prop

步驟 4 — 添加 props

最後的要作的是給咱們的組件附加一些 props

import { compose, withState, withHandlers, withProps } from 'recompose';

export default compose(
  withState('isVisible', 'toggleVis', false),  
  withHandlers({
    toggleVisibility: ({ toggleVis, isVisible }) => {
     return (event) => {
       return toggleVis(!isVisible);
     };
    },
  }),
  withProps(({ isVisible }) => {
    return {
      title: isVisible ? 'This is the visible title' : 'This is the default title',
      message: isVisible ? 'Hello I am Visible' : 'I am not visible yet, click the button!',
    };
  })
)(Presentation);

這個模式最酷的地方在於咱們如今就能夠操做組件的 props 了,在這裏,經過操做控制可見性的 state,咱們能夠展現不一樣的 title 和 message。依我看,這個加強型組件遠比原來全寫在 render 函數中的方式簡潔。

總結

如今你看到了,咱們有了一個可複用的高階組件,它能夠被用在其餘的展現性組件上。同時能夠看到咱們移除了原來高階組件寫法中的不少樣板語法。

在 Recompose 中還有不少有用的 API,瞭解更多!它真的很是像 Lodash,如今就打開文檔開始寫代碼吧!

若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。

掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄
相關文章
相關標籤/搜索