• React hooks能替代HOC和render props么?


    最近开始学习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。实事求是是为了代码的更好维护。

  • 相关阅读:
    PHP递归复制文件夹以及传输文件夹到其他服务器。
    CSS中的disable,hidden,readonly
    linux下用scp命令在两个服务器之间传输文件,利用php_scp函数进行文件传输
    在PHP中调用php_ssh实现远程登陆linux服务器并执行shell脚本。
    Centos7搭建lamp环境
    Golang 标准库构建 http.Requests 请求
    go modules 的使用
    Golang 自用第三方库
    《Go 语言并发之道》读后感-第五章
    《Go 语言并发之道》读后感
  • 原文地址:https://www.cnblogs.com/yy17yy/p/11485481.html
Copyright © 2020-2023  润新知