React hooks能替代HOC和render props么?

Stella981
• 阅读 905

最近开始学习React,记录一下心得。

React hooks是16.8.0推出的,其目的是为了替换class,HOC,render props。那么本文将讨论啥是hooks,HOC,render props,以及hooks究竟能不能替换掉HOC,render props。

Hooks替代HOC和render props。

首先是hooks(这里指custom hooks,下同),HOC,render props到底是做什么的?

对于新手,并不是很容易理解它们是做什么的,至少我没有很容易理解。

我现在理解为它们是为了共享一些维护state的逻辑。

什么意思呢?首先它共享的是逻辑,但是共享逻辑你随便封装一个函数不就可以了么?问题就出在它是共享维护state的逻辑。普通的逻辑的和维护state的逻辑的区别就是,维护一个state的逻辑,当state发生变化时,用到这个state的组件是要重新渲染的,显然用普通的函数做不了这个事情。

那么有哪些维护state的逻辑呢?我大体上把它们分为两类:

第一类,一个状态组件维护state的逻辑,第二类,一个非组件维护state的逻辑。

其实一个状态组件本身就是在维护一个state,当用户操作它所渲染的UI的时候,state发生响应的变化。组件的逻辑负责维护state的变化。

那么非组件指什么呢?

比如说我维护一个user的登录状态,这个登录状态需要发送请求给后台去拿。那么这个登录状态就会有3个值{fetching,online,offline},而且可能会从fetching到online,或者从fetching到offline,就是会变化的。

比如说我需要记录用户鼠标的位置(x,y坐标),这个是随用户移动鼠标而变化的。

比如说我做一个定时器,每隔一段时间切换一下我维护的一个state。

等等,我相信还有其他很多。

之所以分为这两类,是因为我们不能用hooks来共享状态组件。这是因为我们用hooks的时候是需要用它的返回值的,这个返回值通常是这个hooks所维护的state或者state的计算值,那么这个hooks就不可能返回一个dom元素了,也就是hooks不能包含组件。

然后我们建立一个简单的模型分析下三者的结构。

我们假设有三个组件A,B,C需要共享一个维护state的逻辑S。那么:

hooks是什么呢?hooks就是把S封装成useS,也就是一个custom hooks,然后在A,B,或者C里面使用useS

const useS = () => {
    const [state, setState] = useState('someValue')
    useEffect(() => {
        ...some code...
        setState('anotherValue')
    })
    return state;
}
const A = () => {
    const s = useS();
    return (
        <div>
            <div>{s}</div>
            <div>A</div>
        </div>
    )
}

Render props是什么呢?它是把S封装成一个component,同时这个component留了一个props用来接收需要渲染的组件。我认为下面这两种写法都是render props,因为他们的结构基本一样,结果完全一样。

第一种,就是官方文档的写法:

const S = ({render}) => {
    const [state, setState] = useState('someValue')
    useEffect(() => {
        ...some code...
        setState('anotherValue')
    })
    return render(state)
}

const A = ({s}) => {
    return (
        <div>
            <div>{s}</div>
            <div>A</div>
        </div>
    )
}

const App = () => {
    return <S render = {(s) => <A s={s} />} />
}

 第二种,也是可用的写法。

const S = ({render}) => {
    const [state, setState] = useState('someValue')
    useEffect(() => {
        ...some code...
        setState('anotherValue')
    })
    const Render = render;
    return <Render s={state} />
}

const A = ({s}) => {
    return (
        <div>
            <div>{s}</div>
            <div>A</div>
        </div>
    )
}

const App = () => {
    return <S render = {A} />
}

 可以看到render props相对于hooks有明显的区别,它在被调用的时候需要知道两个component。Render props的两种写法的区别就是第一种是调用的时候render设置为一个函数,返回值为component实例。第二种是render设置为component本身。

HOC是什么呢?HOC就是把S封装成一个函数withS,这个函数返回一个新的component。

const withS =(WrappedComponent) => {
    return () => {
        const [state, setState] = useState('someValue')
        useEffect(() => {
            ...some code...
            setState('anotherValue')
        })
        return <WrappedComponent s={state} />
    }
}
const A = ({s}) => {
    return (
        <div>
            <div>{s}</div>
            <div>A</div>
        </div>
    )
}
const AWithS = withS(A);
const App = () => { return <AWithS />; }

 对比一下HOC和render props,你会发现其实HOC返回的component使用的技术和render props很相似哦!只不过render props的例子中需要render的component来自props,而HOC中需要render的component来自HOC的参数。

当然在react的官方文档中你会发现另一种写法,HOC的返回值调用了用render props技术实现的S。这种写法往往是为了提供API给其他开发者,让喜欢用HOC的去使用HOC,喜欢用render props的去使用render props。

const S = ({render}) => {
    const [state, setState] = useState('someValue')
    useEffect(() => {
        ...some code...
        setState('anotherValue')
    })
    const Render = render;
    return <Render s={state} />
}

const withS = (WrappedComponent) => {
    return () => { return <S render = {(s) => <WrappedComponent s={s} />} /> }
}

const A = ({s}) => {
    return (
        <div>
            <div>{s}</div>
            <div>A</div>
        </div>
    )
}
const AWithS = withS(A);
const App = () => {
    return <AWithS />;
}
const AnotherApp = () => {
    return <S render = {(s) => <A s={s} />} />
}

HOC和hooks一样,在调用的时候只需要知道一个component,上面例子中的AwithS,实际情况是我们命名AwithS为A,而真正的A不被暴露(export)出去,这是很好的行为。

HOC不光是有共享维护state的逻辑的能力,还可以做一切封装能做的事情,比如说偷偷改下上层component传过来的props的值。

Hooks能替代HOC,render props么?

hooks是无法实现共享状态组件逻辑的,当然就无法在这方面代替HOC和render props。而共享非组件逻辑的功能,基本都可以用hooks来替代,而且最好用hooks来实现,因为我们看到了,hooks的逻辑最直接,最容易理解。当然第一原则仍然是根据业务实事求是,就是概念上该是什么就是什么,如果概念上就是HOC,那么就用HOC。实事求是是为了代码的更好维护。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
徐小夕 徐小夕
3年前
10分钟教你手写8个常用的自定义hooks
前言Hook是React16.8的新增特性。它可以让你在不编写class的情况下使用state以及其他的React特性。本文是一篇以实战为主的文章,主要讲解实际项目中如何使用hooks以及一些最佳实践,不会一步步再介绍一遍reacthooks的由来和基本使用,因为写hooks的文章很多,而且官网对于reacthooks的介绍也很详细
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
React系列
React系列Mixin、HOC、RenderProps(上)React系列轻松学会Hooks(中)React系列自定义Hooks很简单(下)我们在第二篇文章中介绍了一些常用的hooks,接着我们继续来介绍剩下的hooks吧useReducer作为useState的替代方案。它接收一个形如(sta
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这