深入理解render props

作者: mytac | 来源:发表于2020-01-10 01:40 被阅读0次

    前言

    自己对render props\hoc\hook的区别和适用场景都不怎么了解

    在写文章前的个人理解:

    render props->体现组件之间的父子关系,非常灵活
    hoc ->更加突出工厂模式
    hooks -> 让函数组件更加贴近类组件
    

    render props

    第一次看官方文档的时候,觉得render props就是渣男制造机啊哈哈。至于为什么用“渣男”这个词来描述组件,因为“渣男”普适性高,独立性强,所以可以更好的复用,请看下方例子有更加传神的描述。

    初步了解

    官方例子是要实现一个这样的效果,猫随着鼠标动

    demo

    Mouse组件

    <div className="Mouse" onMouseMove={this.handleMouseMove}>
        <p>position is ({x},{y})</p>
        <Cat x={x} y={y}/>
    </div>
    

    代码中有一个<Mouse>组件跟踪鼠标位置,将位置信息传给<Cat>,然后<Cat>组件根据Mouse传给他的信息进行显示。但是这里,Cat是Mouse的子组件,就显得不够分离了。如果你要改成狗、改成猪可以新增一个prop传图片,但是如果想鼠标经过的位置弄一些炫酷的特效,是不是就得重新写一遍获取鼠标的逻辑了~(我们设计一个组件的时候,要提高他的复用性,就要让他能处理更多的场景,所以他的功能必须更加的独立、单一,才能更好的将组件们组合起来。)

    好在render props就提供了一个简单的复用的思路:Cat还是依赖Mouse里state的变化,state还是要传给Cat,但是经过render props一整,二者如胶似漆的状态就变得更加分离,Mouse拥有了渣男属性。对于Mouse组件来说,之前

    “我心中只有你,我的state的改变是为你而存在”

    的忠犬形象颠覆了,但现在

    “我也可以和更多类型的组件一起为开发者大人干活了,小Cat你只是我的备胎之一哦~~”

    但悲剧的事,对于Cat组件来说,还是那个傻瓜组件,一行代码都不用改,仍然纯洁得一塌糊涂!!

    把Mouse和Cat写在同一个层级,将Cat作为render props传给Mouse组件,如下:

    // App.js
    function App() {
      return (
        <div className="App">
        {/* 这里的函数prop名字叫啥都行!不是说非得叫render */}
         <Mouse render={(props)=><Cat {...props}/>}/>
        </div>
      );
    }
    
    // Mouse.js
    handleMouseMove(e){
            const {clientX,clientY}=e
            this.setState({
                x:clientX,
                y:clientY
            })
    }
    
    // 省略了很多代码
    
    <div className="Mouse" onMouseMove={this.handleMouseMove}>
        <p>position is ({x},{y})</p>
        {this.props.render({x,y})}
    </div>
    

    render props是一个用于告知组件用于渲染什么内容的函数prop,他把组件可以动态渲染的地方暴露给外部,你不用再关注组件的内部实现,只要把数据通过函数传出去就好。

    render props有什么好处?坏处?具体应用

    相关阅读:Comparison: HOCs vs Render Props vs Hooks
    这篇文章提到(我以为michael jackson是作者瞎掰的,居然确有其人):

    A Render Prop is a function prop that a component uses to know what to render.

    render props让组件知道他自己里边渲染了什么??其实也就是让开发者知道包裹的这个组件里边具体包含了什么组件,传了什么props进去,而不是像之前传统写法那样对于里面的组件一无所知,增强了代码的可读性。

    如果传多个renderProps,明显可读性增加了不少/

    // Login.jsx
    <LoginForm
      renderButton={(DefaultButton, buttonProps) => (
        <DefaultButton {...buttonProps}>{value}</DefaultButton>
      )}
      renderInput={
        ...
      }
      renderCheckBox={
        ...
      }
    />
    

    与几个小兄弟一起为开发者大人干活,干杯!

    与Hooks结合

    官方文档

    export default function Mouse(props){
        const [pos,setPosition]=useState({x:0,y:0})
        return (
            <div className="Mouse" onMouseMove={(e)=>setPosition({x:e.clientX,y:e.clientY})}>
                    <p>position is ({pos.x},{pos.y})</p>
                    {props.render({x:pos.x,y:pos.y})}
                </div>)
    }
    

    妈呀,代码一下子清爽好多!不用再写什么class ... extends React blabla的东西了。

    扩展:hooks好处?坏处?注意事项

    好处:代码少了!可以用functional组件代替class了。不用bind this了(一直以来的诟病)!!(官方文档提到:class写的组件不能很好的压缩,使热重载不稳定--但不知道为什么,希望可以得到解答)

    注意事项:只能在函数最外层调用hook,不要在循环、条件判断或子函数中调用。

    弊端:墙裂推荐阅读-> React Hooks 你真的用对了吗?

    以下概括:

    1. hook依赖的数组元素过多,难以维护,比如:
    const refresh = useCallback(() => {
      // ...
    }, [name, searchState, address, status, personA, personB, progress, page, size]);
    
    1. useMemo、useCallback的滥用。比如对于:
    const resolveValue=useMemo(()=>{return compute(a,b)},[a,b]) 
    

    如果compute()是一个非常简单的计算,使用useMemo可能会带来比直接计算更大的开销。所以在进行大型计算时使用会更好。第二个是,resolveValue值是否为对象类型,如果是对象类型因为比较的是引用,每次函数调用都会产生新的引用,所以这里用useMemo就比较合适了,但如果是原始值的时候就没什么必要,上文作者建议用useMemo来保持值的一致性。

    再加上HOC

    如果这种组件要用的地方很多,想扩展更多的功能,比如说这个例子中处理props,或进行渲染劫持

    推荐阅读-> 深入理解 React 高阶组件

    export default function withMouse(Component) {
        return class extends React.Component {
          handleProps(){
           // ...do something to props 
          }
          render() {
            const newProps=this.handleProps()
    
            return (
              this.props.logIn
              ?
              (<Mouse render={positions => (
                <Component {...newProps} {...positions}  />
              )}/>)
              : null
            );
          }
        }
    }
    

    hoc好处坏处??

    好处:处理场景适用性很广,更加体现工厂模式。

    坏处:嵌套的问题比较讨厌,不好调试。对props的劫持,不小心就污染了包裹的组件。

    结尾

    强烈推荐阅读这篇文章!!!Comparison: HOCs vs Render Props vs Hooks。尤其是文章后半部分,作者从可读性、复用性、定制化、调试、可测性和性能几个角度来比较这三个小兄弟,最后从开发者角度上来看render props比hooks略胜一筹,把hoc远远的甩在后边。

    hoc当然没有他说的那么难用,还是看场景,起码hoc可以做很多render props不能做的事情。当然hooks也无法代替他, 推荐阅读:什么是 HOC 适合做而 React Hooks 不适合的场景? - 程墨Morgan的回答 - 知乎

    最后请大家关注我的订阅号获得更加及时的推送~

    那屋水泡

    相关文章

      网友评论

        本文标题:深入理解render props

        本文链接:https://www.haomeiwen.com/subject/ejzuactx.html