后生,React-Hooks了解一下

若是你以为能够,请多点赞,鼓励我写出更精彩的文章🙏。若是你感受有问题,也欢迎在评论区评论,三人行,必有我师焉javascript

若是是你一个React开发者,或多或少接触了React 16.8的一些新特性。例如:React.memo()React.lazyReact.Suspense等一些比较好的新特性。可是,其中我认为,最爽的是React-Hooks的提出。html

这意味着啥,React项目组,对性能要求更加严格(Hooks推崇的是函数组件,在渲染速度上是比类组件快很多)。无论你是不是一个React开发的老鸟,可是在实际项目开发中,确定见过让人头疼的代码堆砌java

尤为在一些公司早期的项目代码中,组件化的思惟很匮乏,直接是按一个页面一个组件。一个生命周期的方法中嵌套着5-10个不相关的代码。原来我在某东的时候,有的组件甚至是1000行代码,就是纯粹的去堆砌一些逻辑。长此以往,就变成了一些魔鬼代码,让人望而生畏。react

Hooks的出现,对一些魔鬼代码的出现,有了一些制约。(其实之因此会出现魔鬼代码,仍是因为研发团队对如何进行组件划分或者是逻辑复用的认知度不够而致使的)。git

虽然,不用Hooks,利用HOC/Render Props也能够实现组件化和逻辑复用。可是在实际项目开发中,发现不论是HOC仍是Render Props将组件进行屡次嵌套,就会陷入wrapper hell。若是你开发中用过React-dev-tools看页面。就会发现,一个简单的组件,被层层包裹。那场面简直是车祸现场,惨不忍睹。github

和你们墨迹了半天,算是对现有的React的开发模式的吐槽吧。客官,不要着急离开,这就正式进入正题。编程

今天带你们来看看Hooks中比较基础的API:useState/useEffect。至于像其余的自定义hook,会专门有一篇文章来给你们详细讲述。json

顺便提一句,这篇文章只是一个Hooks的简单介绍和入门。这个技术方案是针对函数组件的。想了解为何FaceBook构建了这个技术方案,或者是解决了什么技术痛点。 能够参考官网api

TL;DR

  • Hooks究竟是啥?
  • State Hook
  • useState的语法解析
  • useState的返回值
  • 构建多个State Hooks
  • Effect Hook
  • 有条件的调用Effect Hook
  • componentWillUnmount()什么时候调用
  • 同时使用State和Effects
  • 汇总

Hooks究竟是啥?

React Hooks是将React.Component的特性添加到函数组件的一种方式。数组

例如将

  • State
  • 组件生命周期

Hooks可以让开发者不使用class来使用React的特性

可能你们会问,是否是之后React官网就不会继续维护用class来构建组件的方式了。这一点大可没必要担忧。

同时也有一点须要你们清楚就是:Hook的出现只是新增了一种处理逻辑的方式,而不是让你将原有的类组件重写为函数组件。

State Hook

假如咱们有以下的组件

传统的类组件

import React, { Component } from 'react';

class JustAnotherCounter extends Component {
  state = {
    count: 0
  };

  setCount = () => {
    this.setState({ count: this.state.count + 1 });
  };

  render() {
    return (
      <div>
        <h1>{this.state.count}</h1>

        <button onClick={this.setCount}>计算</button>
      </div>
    );
  }
}
复制代码

利用useState在函数组件中使用state

import React, { useState } from 'react';

function JustAnotherCounter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <h1>{count}</h1>
      <button onClick={() => setCount(count + 1)}>计算</button>
    </div>
  );
}

复制代码

useState的语法解析

你可能对useState()的语法不是很熟悉。可是发现,它是使用了数组的解构语法。这就像咱们经过对象的解构从某个对象中剥取一些特定属性同样。

让咱们经过比较对象的解构和数组的解构,来看看useState是如何选择了数组的解构。

对象解构

const users = { admin: 'chris', user: 'nick' };

// 获取admin和user而且为他们起一个别名 
const { admin: SuperAdmin, user: SuperUser } = users;
复制代码

在进行对象结构的时候,若是须要对解构的属性起一个别名,就须要用额外的变量去接收。而咱们经过数组结构的话,咱们只须要定义须要接收数组值的变量便可。第一个变量就是数组中的第一个值

数组解构

// 
const users = ['chris', 'nick'];

// 获取值的同时为值起了别名
const [SuperAdmin, SuperUser] = users;
复制代码

useState的返回值

useState返回了两个变量,而且经过上文的分析,咱们能够给这两个变量随意起名字。

  • 第一个变量其实一个值,相似于类组件中的this.state
  • 第二个变量是一个函数,用于更新第一个变量的值。相似于类组件中的this.setState

在咱们调用useState的时候,传入了一个值,这个值是做为第一个变量初始值

构建多个State Hooks

因为在实际开发中一个逻辑片断不可能细分到只有一个state去维护和控制,因此Hooks支持在一个函数组件中,屡次调用useState添加多个状态值。

import React, { useState } from 'react';

function AllTheThings() {
  const [count, setCount] = useState(0);
  const [products, setProducts] = useState([{ name: 'Surfboard', price: 100 }]);
  const [coupon, setCoupon] = useState(null);

  return <div>{/此处能够随意使用已经构建的状态值/}</div>;
}
复制代码

Effect Hook

State Hook让咱们能够在函数组件中使用state,让函数组件在使用上变得更加灵活。而Effect Hook使得函数组件拥有了生命周期方法

函数组件中的Effects其实等同于类组件的componentDidMountcomponentDidUpdatecomponentWillUnmount的结合体

字如其名,Effect就是维护一些具备反作用的操做

  • 获取远程接口数据
  • 操做DOM
  • 响应订阅操做

Effects在每次render以后触发,无论组件是不是首次渲染

具备副操做的类组件

import React, { Component } from 'react';

class DoSomethingCrazy extends Component {
  componentDidMount() {
    console.log('我要起飞了!');
    document.title = '这是标题';
  }

  render() {
    return <div>作点疯狂的事</div>;
  }
}
复制代码

useEffect修改组件

function DoSomethingCrazy() {
  useEffect(() => {
    console.log('我要起飞了');
    document.title = '这是标题';
  });

  return <div>作点疯狂的事</div>;
}
复制代码

经过比较,是否是感受利用useEffect在代码量上还有逻辑捆绑上比传统的组件都具备很大的优点。

有条件的调用Effect Hook

因为useEffect()在每次render的以后,总会被调用。那咱们是否有一个方式,只限制它在首次加载时调用。

其实Effect Hook接收第二个参数(Array类型)。只有数组中的值发生变化了,才会调用useEffect()而不是每次在渲染的时候调用。

componentDidMount: 只运行一次

// 当第二个参数为空数组([])的时候,只是被调用一次(也就至关于类组件中componentDidMount)
useEffect(() => {
  // 值运行一次
}, []);
复制代码

componentDidUpdate: 根据值是否变化来运行

// 只有count变化才运行
useEffect(
  () => {
  //只有count变化才运行
  },
  [count]
);
复制代码

componentWillUnmount()什么时候调用

咱们上文说过,函数组件中的Effects其实等同于类组件的componentDidMountcomponentDidUpdatecomponentWillUnmount的结合体。而经过控制第二个参数的值,能够模拟componentDidMountcomponentDidUpdate。可是componentWillUnmount如何才会调用呢。

咱们只须要在useEffect()中返回一个函数,既能够模拟componentWillUnmount的功能,也就是在组件unmounts时调用。

useEffect(() => {
  UsersAPI.subscribeToUserLikes();

  // unsubscribe
  return () => {
    UsersAPI.unsubscribeFromUserLikes();
  };
});

复制代码

同时使用State和Effects

既然在函数组件中能够单独使用useState来模拟类组件的this.state的功能,用useEffect来模拟类组件的生命周期。那咱们能够同时利用useStateuseEffect将函数组件变成有状态组件

咱们经过一个真实的例子来说解一下如何共同使用这些API。咱们经过useEffect()来获取GitHub API而且用useState()来存储。

使用useState

import React, { useState } from 'react';

function GitHubUsers() {
  const [users, setUsers] = useState([]);
}
复制代码

咱们经过useState([])的参数将users的值,赋为[]

使用useEffect来获取数据

import React, { useState } from 'react';

function GitHubUsers() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    fetch('https://api.github.com/users')
      .then(response => response.json())
      .then(data => {
        setUsers(data); // 为users赋值
      });
  }, []); //经过useEffect的第二个参数,来约定,该操做只被调用一次
}
复制代码

数据展现

import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';

function GitHubUsers() {
  // 刚才的代码

  return (
    <div className="section">
      {users.map(user => (
        <div key={user.id} className="card">
          <h5>{user.login}</h5>
        </div>
      ))}
    </div>
  );
}
复制代码

这样一个简单的Hooks的例子就完成了。

汇总

上面的分析步骤,只是简单介绍了useState/useEffect的使用方式,我相信你们在使用过程当中,确定遇到了比这还复杂的。可是,万变不离其宗。都是利用hook的一些API。为函数组件赋予状态

还有一点,由于在使用useState或者useEffect的时候,咱们能够将相关的代码进行统一处理,这样无论在业务开发仍是代码维护上,变的很清楚。而不是像原来的开发同样,一个生命周期包含着无数的不相干的逻辑代码。

而且,hooks还支持自定义。本人认为,这才是hooks的真正强大之处。经过自定义一些业务代码,真正的实现逻辑复用。能够有效的减小wrapper hell。让代码实现切片化编程

相关文章
相关标签/搜索