【React总结(二)】使用 Render props 复用代码

导语

在 React 当中,我们为了代码的复用,我们通常会封装一个组件。 一个组件通常会包含组件的内容样式组成的业务逻辑。一般情况下,我们会把组件的 js,和 css 放在一个地方,并且像 Linux 的哲学一样,一个组件只做一个事情。 那么我们在了解封装组件的时候,通常开发者们都会聊起 HOCrender props。 HOC 我相信大家在业务里面都用到,那么今天就来分享一下什么是 render props

从 Javascript 的代码复用谈起

现在如果要写一个加法计算器,并且把输出打印在控制台,你会怎么写?

const sum = (a, b)=>{
    let result =  a + b;
    console.log(result);
}

// 用法
sum(1,  1);  
// 2

是的,你很快就可以写出来。

有一天产品产品经理突然找过来和你说,他并不想把这个打印在,控制台,而是像通过弹窗的形式 alert 出来,让用户看见,那么你会怎么做?

直接 console 改为 alert 吗? 有代码洁癖的你肯定想着,我应该想象办法做到代码复用。于是,你写了这样的代码:

const sum = (a, b, cb)=>{
      let result =  a + b;
      cb(result);
}

// 用法
// alert
sum(1, 1, (result) => {
    alert(result)
});
// console
sum(1, 1, (result) => {
    console(result);
});

到现在为止,其实你已经抽象了一个 util 工具方法出来了,他的用途很简单,他不处理具体的业务逻辑,他就专注于计算加法的和运算,至于输出结果怎么处理,那是具体的逻辑决定的,sum 工具函数第三个参数的位置是一个 callback,把函数计算后的返回值,回调给业务逻辑,让业务逻辑使用。

ok,到此处,其实你已经了解了 90% 的 render props 的基础知识。

render props 是什么?

是指一种在 React 组件之间使用一个值为函数的 prop 在 React 组件间共享代码的简单技术。

官方文档说的非常的晦涩。其实说白了,就是在父组件有个 render 的属性,然后 render 属性你可以理解为一个回调函数,父组件通过调用 render 方法,把父组件里面的数据(一般是 state )带出来让业务组件使用,然后,这个回调函数返回一个 React 的 element,然后渲染在父组件里面。

说得比较啰嗦,直接看如下精简代码:

<DataProvider render={data => (
    <h1>Hello {data.target}</h1>
)}/>

例子

React 通过组件来复用代码,但如何共享状态或一个组件的行为封装到其他需要相同状态的组件中,做法却说明得不是很清楚。

举个🌰,现在你有一个按钮🔘,点击以后会弹起来一个弹窗 Modal,那么熟练的你肯定很快就可以写出来。下面我用 antd举个 🌰

import { Button, Modal } from "antd";

class App extends React.Component {
  state = { visible: false };
 
  showModal = () => {
      this.setState({
          visible: true
      });
  };
 
  handleOk = e => {
      this.setState({
          visible: false
      });
  };
 
  handleCancel = e => {
      this.setState({
          visible: false
      });
  };
 
  render() {
        return (
            <div>
                <Button type="primary" onClick={this.showModal}>
                    Open Modal
                </Button>
                <Modal
                        title="普通 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);

也许你会经常写下这样的代码,每次出现 Modal 之类的要控制 toggle 展示隐藏的时候,你都会写几个方法控制他们点击 ok, cancel,和 show,那么,通过 render props 怎么样可以复用代码呢?

请看代码,我们可以封装一个 Toggle的组件 复用上面三个方法。

// demo 代码
class Toggle extends React.Component {
      state = { on: this.props.initial};
      
      toggle = () => {
            this.setState({
                on: !this.state.on
            });
      }

      render() {
            let { on } = this.state;
            let toggle = this.toggle;
            
            this.props.render(on, toggle);
      }
}

class App extends React.Component {
  render() {
        return (
            <Toggle initial={false}  render = {({ on, toggle }) => (
                    <Button type="primary" onClick={toggle}>
                            Open Modal
                    </Button>
                    <Modal
                            title="Basic Modal"
                            visible={on}
                            onOk={toggle}
                            onCancel={toggle}
                    >
                            <p>Some contents...</p>
                            <p>Some contents...</p>
                            <p>Some contents...</p>
                    </Modal>
                )}/>
            );
    }
}

到这里为止,我们成功通过 render props 复用了modal 的 展示隐藏逻辑,通过 render props 可以很容易给受控组件附上一些常用的逻辑与状态。 这里推荐一个写得比较全面的库 react-powerplug

其实 render props 是一种设计模式,除了把写 render 以外,也可以写成任意你喜欢的名字,另外通过 props children也能实现这个功能,并且使用 props children,我们可以做到不要把组件放在 JSX 元素的 “attributes” 列表中,而是可以直接放到 组件内部,例如上面的组件如果是用 children 的方式来写,那么他是这样的:

    <Toggle initial={false}>
        {(on,  toggle) =>  <Button type="primary" onClick={toggle}>
                            Open Modal
                    </Button>
                    <Modal
                            title="Basic Modal"
                            visible={on}
                            onOk={toggle}
                            onCancel={toggle}
                    >
                            <p>Some contents...</p>
                            <p>Some contents...</p>
                            <p>Some contents...</p>
                    </Modal>
        }
    </Toggle>;

总结

到这里,我们已经了解了 react render props 的设计模式是怎么样构建高度可复用的组件的。其实 React hooks 已经 React 16.8 中稳定发布,大家可以尝鲜使用。也可以看我之前写得文章了解 hooks 是什么? 理解 React Hooks

系列文章

【React总结(一)】浅谈 React 中 key

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区