资讯专栏INFORMATION COLUMN

从React函数式组件说到Hooks

lavor / 1029人阅读

摘要:难道还不允许设计得对新人更友好了我们先把做成就是找骂啊这怎么怪到我们头上了事实是,即使在内部,也显然不是所有程序员都熟悉函数式编程的概念。

1.前言介绍

历史
React在2013年开源,在2015引入函数式组件,不过在日常开发中经常被忽略。
ReactJS Core Team 确实大部分成员都曾在推特上公开夸赞过对函数式编程 与 ML 系语言(或其特性)的优点:Sebastian 日常提到 OCaml,Sophie 至少提过 Rust/Kotlin/Swift 并且嫌弃过 Dart 没有 ADT 和 non-nullability,Dan 和 Andrew 的 Redux 主要受 Elm 影响,Dan 曾提过学习高阶函数后省去了一半设计模式,Andrew 的 Recompose 主要利用了函数的组合性,其他成员未知。

为什么引入class组件:

Chenglou: God forbid React api led newcomers into something familiar instead of FP purists’ agendas lol。
难道还不允许 React API 设计得对新人更友好了?
Cristiano: So I guess also making React in JS in the first place was the ultimate trolling.
我们先把 React 做成 JS 就是找骂啊……
Jordan: They"re onto us.
这怎么怪到我们头上了……

事实是,即使在 FB 内部,也显然不是所有程序员都熟悉函数式编程的概念。做一个前端框架是拿来用的,如果有大家熟悉的概念可以对照,为什么刻意要去用大家不熟悉的概念呢?对于迁移至 ES6 Class,主要的目的是为了减少 React 特有的 API,毕竟 并不因为它「接受一个函数」就比 ES6 class 更函数式了……

2.函数式组件和类组件的区别

在之前class组件通常被认为有更多的功能,例如可以拥有state,可以调用生命周期,而现在在hooks引入之后这个说法就不成立了。以前Function组件没有state,所以也叫SFC(stateless functional component),现在更新叫做FC(functional component)。或许你也听说过,这两类组件中,有一类的性能更好。哪一类呢?很多这方面的性能测试,都是 有缺陷的 ,因此要从这些测试中 得出结论 ,不得不谨慎一点。性能主要取决于你代码要实现的功能(以及你的具体实现逻辑),和使用函数组件还是类组件,没什么关系。我们观察发现,尽管函数组件和类组件的性能优化策略 有些不同 ,但是他们性能上的差异是很微小的。

构建时的差别

先看下面两个组件:
函数式组件在父组件中执行的函数的方法:

function Greeting() {
  return 

Hello

; } // Inside React const result = Greeting(props); //

Hello

类组件在父组件中先实例化一个对象,然后执行这个对象上的render方法:

class Greeting extends React.Component {
  render() {
    return 

Hello

; } } // Inside React const instance = new Greeting(props); // Greeting {} const result = instance.render(); //

Hello

运行时的差别

再来看两段代码
一个两秒后执行alter的按钮的函数式组件

function ProfilePage(props) {
    const showMessage = () => {
      alert("我是 " + props.user);
    };
  
    const handleClick = () => {
      setTimeout(showMessage, 2000);
    };
    
    return (
      
    );
  }

一个两秒后执行alter的按钮的函数式组件

class ProfilePage extends React.Component {
    showMessage = () => {
      alert("我是" + this.props.user);
    };
  
    handleClick = () => {
      setTimeout(this.showMessage, 2000);
    };
    
  
    render() {
      return ;
    }
  }

一般我们会认为上面两个组件是完全等价的。开发者经常像上面这样,在函数组件和类组件之间重构代码,却没有意识到他们隐含的差异。然而这两个是有一些差别,你有看出这两个的区别吗?
我们用一个组件将上面两个组件包裹

function App() {
  const [user, setUser] = useState("小码王")
  return (
    

{user}


); }

当我们先点击Class按钮然后再点击changName按钮,alert出的我是小码世界,而我们先点击Function再点击changName,alter出的我是小码王。
为什么会这样呢?
我们可以看到在函数式组件中user是在props中读取的,而在类组件中user是从this.props中读取的,区别就在this上,在react中props是不可变,而this是可变的,所以当父组件的值改变时this也改变了。
有什么方法使类组件也实现函数式组件的效果呢?

class ProfilePage extends React.Component {
  render() {
    // Capture the props!
    const props = this.props;

    const showMessage = () => {
      alert("我是 " + props.user);
    };

    const handleClick = () => {
      setTimeout(showMessage, 2000);
    };

    return ;
  }
}

在render函数中创造了一个props的闭包,这个问题就解决了,是不是感觉段代码比较熟悉,其实在render函数里面的代码抽离出来就是函数式的组件了。所以当函数式组件有render方法以外的功能,就可以实现类组件的任何功能了,这就是hooks了。

3. Hooks

在 Hooks 的协议设计考量上,与原本的 React HoC Design 其实会有很多的不同,主要原因也许就在于 HoC 总的来说是 Props 导向的设计,而 Hooks 则是更 functional 风格的调用形态。并且,HoC 可能会倾向于避免产生过多的 HoC 层级,而产生过深的 VDOM Tree。Hooks 大可以更自由地讲更多的 use 方法分离式的调用,也能够得到更大的自由度;
Hooks解决的问题

代码重用:在hooks出来之前,常见的代码重用方式是HOCs和render props,这两种方式带来的问题是:你需要解构自己的组件,同时会带来很深的组件嵌套

复杂的组件逻辑:在class组件中,有许多的lifecycle 函数,你需要在各个函数的里面去做对应的事情。这种方式带来的痛点是:逻辑分散在各处,开发者去维护这些代码会分散自己的精力,理解代码逻辑也很吃力

class组件的困惑:对于初学者来说,需要理解class组件里面的this是比较吃力的(这个理由有点勉强~),同时,基于class的组件难以优化(举个不恰当的例子,看一下babel转移出来的class代码量增长了多少)

从react team 公布 hooks的概念时,淘宝内部做了一些简单的研究与调研,结论是hooks是类react体系的未来主流编程模式,无论是基于hooks后业务代码会更简练还是复用更容易,这些都是降低了react 编程的门槛。
尤雨溪也称vue3.0的特性吸取了很多hooks的灵感,并在最新的RFC(意见征求稿)中发布了Function API + Hooks 。

Hooks的API

React Hook让无狀态组件拥有了许多只有有狀态组件的能力,如自更新能力(setState,使用useState),访问ref(使用useRef或useImperativeMethods),访问context(使用useContext),使用更高级的setState设置(useReducer),及进行类似生命周期的阶段性方法(useEffect或useLayoutEffect)。

hooks之间的关系 useState useReducer useRef关系
function useReducer(reducer, initialArg,init){     
  var initialState = void 0;      
  if (init !== undefined) {        
    initialState = init(initialArg);
  } else {        
    initialState = initialArg;
  }
  function dispatch(action){          
    memoizedState = reducer(memoizedState,action);          
    render();      
  }      
  memoizedState =  memoizedState||initialState;      
  return  [memoizedState, dispatch]; 
}

function useState(initialState){    
  return  useReducer((oldState, newState)=>newState, initialState); 
}
​useRef() ===  useState({current: initialValue })[0]
useEffect useLayoutEffect的关系

useMemo useCallback的关系

useCallback和useMemo的参数跟useEffect一致,他们之间最大的区别有是useEffect会用于处理副作用,而前两个hooks不能。

 useMemo和useCallback都会在组件第一次渲染的时候执行,之后会在其依赖的变量发生改变时再次执行;并且这两个hooks都返回缓存的值,useMemo返回缓存的变量,useCallback返回缓存的函数。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/105819.html

相关文章

  • 全面了解 React 新功能: Suspense 和 Hooks

    摘要:他们的应用是比较复杂的,组件树也是非常庞大,假设有一千个组件要渲染,每个耗费一千个就是由于是单线程的,这里都在努力的干活,一旦开始,中间就不会停。 悄悄的, React v16.7 发布了。 React v16.7: No, This Is Not The One With Hooks. showImg(https://segmentfault.com/img/bVblq9L?w=97...

    Baaaan 评论0 收藏0
  • 通过 React Hooks 声明地使用 setInterval

    摘要:但我认为谈不上的毛病,而是编程模型和之间的一种模式差异。相比类,更贴近编程模型,使得这种差异更加突出。声明本文采用循序渐进的示例来解释问题。本文假设读者已经使用超过一个小时。这是通过组件生命周期上绑定与的组合完成的。 本文由云+社区发表作者:Dan Abramov 接触 React Hooks 一定时间的你,也许会碰到一个神奇的问题: setInterval 用起来没你想的简单。 R...

    NoraXie 评论0 收藏0
  • 十个案例学会 React Hooks

    摘要:在线传递给的是而不是,返回值即是想要透传的数据了。所以函数组件在每次渲染的时候如果有传递函数的话都会重渲染子组件。在学会使用React Hooks之前,可以先看一下相关原理学习React Hooks 前言 在 React 的世界中,有容器组件和 UI 组件之分,在 React Hooks 出现之前,UI 组件我们可以使用函数,无状态组件来展示 UI,而对于容器组件,函数组件就显得无能为力,我...

    williamwen1986 评论0 收藏0
  • React Hooks 入门到上手

    摘要:前言楼主最近在整理的一些资料,为项目重构作准备,下午整理成了这篇文章。给传入的是一个初始值,比如,这个按钮的最初要显示的是。取代了提供了一个统一的。 showImg(https://segmentfault.com/img/bVbpUle?w=900&h=550); Hooks are a new addition in React 16.8. They let you use sta...

    XFLY 评论0 收藏0
  • React Hooks 入门到上手

    摘要:前言楼主最近在整理的一些资料,为项目重构作准备,下午整理成了这篇文章。给传入的是一个初始值,比如,这个按钮的最初要显示的是。取代了提供了一个统一的。 showImg(https://segmentfault.com/img/bVbpUle?w=900&h=550); Hooks are a new addition in React 16.8. They let you use sta...

    zhouzhou 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<