後生,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。讓代碼實現切片化編程

相關文章
相關標籤/搜索