[译] 使用 Recompose 来构建高阶组件

栏目: 后端 · 发布时间: 5年前

内容简介:在Workpop 公司,我们不断使用不同的组件设计模式来迭代我们的产品,以适应瞬息万变的 React 生态系统。早些时候,我们从试用高阶组件设计模式(HOC)中尝到一点甜头。这里有个例子:正如你看到的这个例子,我们只有一个给你的组件提供功能的函数。在本例中,我们添加了一些

在Workpop 公司,我们不断使用不同的组件 设计模式 来迭代我们的产品,以适应瞬息万变的 React 生态系统。早些时候,我们从试用高阶组件设计模式(HOC)中尝到一点甜头。

什么是高阶组件?

高阶组件只是一个函数,只不过它返回的是用来渲染 React 组件的函数。

这里有个例子:

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 来控制可见性。

我们可以看看它的使用方式:

// 展示型组件

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

步骤 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前端后端区块链产品设计人工智能 等领域,想要查看更多优质译文请持续关注 掘金翻译计划 、官方微博、 知乎专栏


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Introduction to Programming in Java

Introduction to Programming in Java

Robert Sedgewick、Kevin Wayne / Addison-Wesley / 2007-7-27 / USD 89.00

By emphasizing the application of computer programming not only in success stories in the software industry but also in familiar scenarios in physical and biological science, engineering, and appli......一起来看看 《Introduction to Programming in Java》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试