爲什麼會出現Hook
- 難以複用類組件之間的邏輯
- 生命週期中經常包含一些莫名其妙的不相關邏輯
- 類組件難以被機器和人理解
React核心算法的改變
在V16版本之前 協調機制 是 Stack reconciler, V16版本發佈Fiber 架構後是 Fiber reconciler。新的架構使原來同步渲染的組件現在可以異步化,可中途中斷渲染,執行更高優先級的任務。
在React 16中,在dom真正render之前,React中的調度機制可能會不定期的去查看有沒有更高優先級的任務,如果有,就打斷當前的週期執行函數(哪怕已經執行了一半),等高優先級任務完成,再回來重新執行之前被打斷的週期函數。這種新機制對現存週期函數的影響就是它們的調用時機變的複雜而不可預測,這也就是爲什麼在16改動生命週期的原因
爲什麼要改變核心算法
在Stack reconciler機制下,如果有一個很大,層級很深的組件,react渲染它需要幾十甚至幾百毫秒,在這期間,react會一直佔用瀏覽器主線程,任何其他的操作(包括用戶的點擊,鼠標移動等操作)都無法執行。
好似一個潛水員,當它一頭扎進水裏,就要往最底層一直遊,直到找到最底層的組件,然後他再上岸。在這期間,岸上發生的任何事,都不能對他進行干擾,如果有更重要的事情需要他去做(如用戶操作),也必須得等他上岸
Fiber架構就是爲了解決這個問題。
沒有了生命週期,如何實現在函數組件中實現生命週期的功能
開始覺得Hook就是在函數組件中使用生命週期,越用越發現不是這麼回事。Hook幾乎是摒棄了生命週期的概念,useEffect一個狀態足以應付,扔一篇文章https://overreacted.io/zh-hans/a-complete-guide-to-useeffect/ 由react作者寫的useEffect 指南、看完對理解useEffect\hook都很有幫助
使用React.memo(Component)代替PureComponent優化性能(代替shouldComponentUpdate )
替代componentDidMount
useEffect(() => {
}, []);
替代 componentDidUpdate
const mounting = useRef(true);
useEffect(() => {
if (mounting.current) {
mounting.current = false;
} else {
fn();
}
});
替代componentWillReceiveProps中拿previousProps
function Counter() {
const [count, setCount] = useState(0);
const prevCount = usePrevious(count);
return (
<h1>
Now: {count}, before: {prevCount}
</h1>
);
}
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
替代 forceUpdate
const [ignored, forceUpdate] = useReducer(x => x + 1, 0);
function handleClick() {
forceUpdate();
}
react-router 爲hook新增 ( version >= 5.0)
- useHistory
- useLocation
- useParams
- useRouteMatch
等價關係
const history = useHistory()
history.push() = this.props.history.push()
const location = useLocation()
location.state = this.props.location.state(獲取不在地址欄出現的參數)
const params = useParams()
useParams().xx = this.props.match.params.xx(獲取在地址欄可見的參數)
在使用router新特徵時要注意先聲明變量,再在函數內使用。所有use的聲明都是不能放在內部函數、變量內。
useRouteMatch與上面不太像:
import { Route } from "react-router-dom";
function BlogPost() {
return (
<Route
path="/blog/:slug"
render={({ match }) => {
return <div />;
}}
/>
);
}
import { useRouteMatch } from "react-router-dom";
function BlogPost() {
let match = useRouteMatch("/blog/:slug");
return <div />;
}
可以在下面圖中找到其對應的屬性
react-redux爲hook新增(version >= 7.1.0)
useSelector() 代替 mapStateToProps
useDispatch() 代替 mapDispatchToProps
useStore() 獲取store