React Hooks 可以為我們帶來什麼,及為什麼我覺得React才是前端的未來
簡單說明一下,react hooks 是一個已經在提議中的新功能,預計會隨著React 16.7.0一起釋出。 /以上所述所有React均指ReactJS,下述會用React簡稱/
要明白什麼是React Hooks,那可能先了解一下它的兩個替代品HOC和FaCC/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
首先要說明一下,在16.6的更新裡面,stateless/functional component已經可以進行state操作了,叫做React.memo()。進行這個說明是為了讓大家理解,為什麼functional component也可以使用state了。 而在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結構卻也更復雜了。 從
變成
再到
更重要的原因是,我覺得ReactHooks寫起來更加簡單,易懂,易讀。
我想通過上述的程式碼比對,不難得出這個結論。
試想一下,在一個龐大專案裡面,廣泛使用HOC們,會帶來什麼樣的程式碼複雜度?
為什麼我覺得React才是前端的未來
正如我在前文描述的那樣,不論是HOC還是FACC/Render Props,都有自己的技術上手難度以及理解困難的地方。 但是React Hooks的出現解決了這些問題。
一定有人不贊同,不負責任的猜測大概原因如下
- 行業本身需要有一定的技術門檻,寫法和理解的困難是個體本身的學習能力以及鑽研程度的問題,框架不應該為此埋單。
- React hooks 本身從寫法實現上來說,違背一些JS的規範和趨勢,如純函式。
我的解答如下
- 技術門檻不錯,但是我覺得技術是用來改變生活的,而不是為了讓部分人找到工作。就好比開車有職業賽車手,也有普通在道路上開車的司機。作為專業從事這個行業的人員來說,我們是應該鑽研以及理解一門技術。但是,如果一個後端的同事,或者一個初創小團隊,需要做一個這樣的東西。我覺得,技術簡潔好實現,對他們來說應該是一個吸引點。
- 很多庫為了實現一些簡潔的功能,都會出現這樣或那樣的“奇怪”寫法,這點認同。但是,有時候是需要一些取捨。
而我認為目前前端框架裡面,能察覺到用簡單的方式來處理日趨複雜的業務,這件事的,Angular, Vue 都還沒有做到。 Angular非常完整,但是學習曲線相對陡。 Vue正在面臨整庫重寫。 只有React,用簡單的方式來處理複雜業務,並且第三方庫生態鏈非常龐大。
所以,我看好它。