React Hooks 可以為我們帶來什麼,及為什麼我覺得React才是前端的未來

極度狂熱發表於2019-03-04

簡單說明一下,react hooks 是一個已經在提議中的新功能,預計會隨著React 16.7.0一起釋出。
/以上所述所有React均指ReactJS,下述會用React簡稱/

要明白什麼是React Hooks,那可能先了解一下它的兩個替代品HOCFaCC/Render Props

HOC(Higher-Order Components),React高階元件

如果我們有一個需要共享的狀態,需要在多個元件之間傳遞。我們會怎麼做?
或者說,當多個元件有公用的部分的時候,我們會選擇怎麼做?

例如:

// ComponentA
import React, { Component } from "react";

export default class ComponentA extends Component {
  state = { toggle: false };
  click = () => {
    this.setState({ toggle: !this.state.toggle });
  };

  render() {
    const { toggle } = this.state;
    return (
      <div className="App">
        <button onClick={this.click}>Toggle Name</button>
        {toggle && <div>ComponentA</div>}
      </div>
    );
  }
}
複製程式碼

這裡我們舉一個極端的例子,讓ComponentB和A做一樣的事情

// ComponentB
export default class ComponentB extends Component {
  state = { toggle: false };
  click = () => {
    this.setState({ toggle: !this.state.toggle });
  };

  render() {
    const { toggle } = this.state;
    return (
      <div className="App">
        <button onClick={this.click}>Toggle Name</button>
        {toggle && <div>ComponentB</div>}
      </div>
    );
  }
}
複製程式碼

可以看到程式碼重複的部分非常多,只有文字顯示的不同而已。
這裡就需要用到HOC了。

使用HOC之後,變成

// ComponentA
import React, { Component } from "react";
import HOC from "./HOC";

class ComponentA extends Component {
  render() {
    return <div>ComponentA</div>;
  }
}

export default HOC(ComponentA);
複製程式碼

ComponentB同上。

這裡HOC的寫法就是提出共有的部分,接收一個Component進行渲染。

const HOC = WrapperComponent =>
  class HOC extends Component {
    state = { toggle: false };
    click = () => {
      this.setState({ toggle: !this.state.toggle });
    };

    render() {
      const { toggle } = this.state;
      return (
        <div className="App">
          <button onClick={this.click}>Toggle Name</button>
          {toggle && <WrapperComponent />}
        </div>
      );
    }
  };

export default HOC;
複製程式碼

可以發現,讓公用的部分提取了出去,並且讓程式碼看起來更簡單舒服了一些。每一個元件只需要關注自己內部的狀態,而公有的部分以及共享狀態的部分就交給HOC去解決。
這樣不論再加多少個類似的Component,都無需大量的寫重複程式碼了。

FaCC(Function as Child Component)

原理和HOC差不多,只是運用到了一個叫做 children的react props
可以講程式碼簡化成

//ComponentA
export default class ComponentA extends Component {
  render() {
    return <FaCC>{toggle => toggle && <div>ComponentA</div>}</FaCC>;
  }
}
複製程式碼
//FACC
export default class FaCC extends Component {
  state = { toggle: false };
  click = () => {
    this.setState({ toggle: !this.state.toggle });
  };

  render() {
    const { toggle } = this.state;
    return (
      <div className="App">
        <button onClick={this.click}>Toggle Name</button>
        {this.props.children(toggle)}
      </div>
    );
  }
}
複製程式碼

Render Props是用的一樣的方法,只是換了別的屬性,不用children而已

那麼HOC們,還能做什麼?

通過上述的行為,我們已經發現了,它們可以共用很多部分的程式碼。
如果再深入思考一下,就可以想到,在複雜的業務邏輯裡面,如果傳送同一個API請求的haul,我們不應該在每一個獨立component裡面傳送一個請求。因為它們共享了同一個state,這樣會造成資源的浪費。
我們將HOC的部分程式碼更改一下,例如:

const HOC = WrapperComponent =>
  class HOC extends Component {
    state = { toggle: false, data: {} };
    fetchData = () => {
      fetch("/api", params).then(response => {
        const { data } = data;
        this.setState(data);
      });
    };
    componentDidMount(){
        this.fetchData();
    }

    render() {
   /*......*/
  };

export default HOC;
複製程式碼

React Hooks

在Hooks裡面利用它的Effect,可以讓我們使用到和Component一樣的部分生命週期。
關於ReactHooks的詳細介紹,我會在別的文章進行詳細描述。
在這裡,我想進行的是React Hooks,HOC,FACC的比較。

那麼如果想實現上述功能,React Hooks會怎麼做呢?

// Hooks
import { useState, useEffect } from "react";

const useHooks = () => {
  const [data, setData] = useState(null);

  const fetchData = () => {
    fetch("/api", params).then(response => {
      const { data } = data;
      setData(data);
    });
  };

// Effect,這裡相當於componentDidMount
  useEffect(() => {
    fetchData();
  });

  return data;
};

export default useHooks();
複製程式碼

在Component中需要用到公用的這個data的時候,我們只需要這樣做

  render() {
  // 這一行便是呼叫data的方法了
    const data = Hooks();
    return <div>{data}</div>;
  }
複製程式碼

ReactHooks的優點?

使用ReactHooks無需複雜的DOM結構。

使用HOC們,去除掉了重複應用的問題。
可是開啟React Dev Tool,我們會發現,我們的DOM結構卻也更復雜了。

React Hooks 可以為我們帶來什麼,及為什麼我覺得React才是前端的未來

變成

React Hooks 可以為我們帶來什麼,及為什麼我覺得React才是前端的未來

再到

React Hooks 可以為我們帶來什麼,及為什麼我覺得React才是前端的未來

更重要的原因是,我覺得ReactHooks寫起來更加簡單,易懂,易讀。

我想通過上述的程式碼比對,不難得出這個結論。

試想一下,在一個龐大專案裡面,廣泛使用HOC們,會帶來什麼樣的程式碼複雜度?

為什麼我覺得React才是前端的未來

正如我在前文描述的那樣,不論是HOC還是FACC/Render Props,都有自己的技術上手難度以及理解困難的地方。
但是React Hooks的出現解決了這些問題。

一定有人不贊同,不負責任的猜測大概原因如下

  1. 行業本身需要有一定的技術門檻,寫法和理解的困難是個體本身的學習能力以及鑽研程度的問題,框架不應該為此埋單。
  2. React hooks 本身從寫法實現上來說,違背一些JS的規範和趨勢,如純函式。

我的解答如下

  1. 技術門檻不錯,但是我覺得技術是用來改變生活的,而不是為了讓部分人找到工作。就好比開車有職業賽車手,也有普通在道路上開車的司機。作為專業從事這個行業的人員來說,我們是應該鑽研以及理解一門技術。但是,如果一個後端的同事,或者一個初創小團隊,需要做一個這樣的東西。我覺得,技術簡潔好實現,對他們來說應該是一個吸引點。
  2. 很多庫為了實現一些簡潔的功能,都會出現這樣或那樣的“奇怪”寫法,這點認同。但是,有時候是需要一些取捨。

而我認為目前前端框架裡面,能察覺到用簡單的方式來處理日趨複雜的業務,這件事的,Angular, Vue 都還沒有做到。
Angular非常完整,但是學習曲線相對陡。
Vue正在面臨整庫重寫。
只有React,用簡單的方式來處理複雜業務,並且第三方庫生態鏈非常龐大。

所以,我看好它。

相關文章