在專案中的更換 React Hooks 注意事項

傻夢獸發表於2019-07-16

React 官方有說建議使用Hooks來管理你的專案,不過React 也說過不會放棄Class,網上說了一堆Hooks的說法。可是都是複製貼上居多。

Hooks出了好一段時間了,我今天才去了解,谷歌上也給出了很多解決方案了。

我先說說為什麼推薦使用Hooks?

其實hooks的這種寫法也不是很新鮮的事,早在antd的官方文件(類似hooks的元件寫法),哪裡的文件案例就不是我們一般人用的class寫法,導致我很多時候都需要再改寫一次。現在的文件已經由另一個人管理了吧寫法都改回了Class寫法。

原因很簡單,因為寫程式碼寫少了很多。沒有this,沒有生命週期,不需要.bind(this),就這麼簡單。

在React Hooks 裡面我們只需記住兩個常用的方法即可。useState,useEffect。用來管理自身狀態使用的。

useState 看就知道使用狀態,只是和以前的寫法有出入的是

const [state,setState] = useState(defaultValue);
複製程式碼

你要類似Get Set的東西給定義好。

useEffect 你可以簡單的看成 componentDidMountcomponentDidUpdatecomponentWillUnmount這樣一個順序的生命週期結合版。

上面的東西就不說了,自己百度或者谷歌,網上一堆那個計算器的例子。

React-Router 在Hooks 裡面的使用

由於Hooks沒有this這個概念,所以以前使用的this.props.history.push()this.props.history.goBack() 這些都無法使用了這型別的JS跳轉。

在這裡我們需要一個第三方的庫use-react-router

import useReactRouter from 'use-react-router';
const {history,location,match} = useReactRouter();
history.goBack()
history.push('')
複製程式碼

其他的Router用法和Route的一模一樣,沒有改變。

Reducers 狀態管理

這個肯定是每個React 都關心的一個點

store.js

import {createStore} from 'redux';
import reducer from './reducers';

export const store  = createStore(reducer);
複製程式碼

那reducers.js有什麼呢?

const initialState = {
    counter: 0
}

export default function reducer(state = initialState,action){
    switch(action.type){
        case "INCREMENT":
            return {counter: state.counter+1}
        case "DECREMENT":
            return {counter: state.counter-1}
        default:
            return state;
    }
}
複製程式碼

如果使用react-redux

只要將component(也就是Counter)放在Provider之內,就可以在Counter裡面讀取Redux Store。 再用connect把Counter串在一起才能把store傳抵。

在Hooks建議使用 Redux-React-Hooks

import * as React from 'react';
import {StoreContext} from 'redux-react-hook';
import ReactDOM from "react-dom";
import {store} from './store';
import Counter from './Counter';

ReactDOM.render(
  <StoreContext.Provider value={store}>
      <Counter name="Sara" />
  </StoreContext.Provider>, 
  document.getElementById("root")
);
複製程式碼

基本上除了Provider一個component及其props需要更改外,其他皆與react-redux的例子無異。

最大的更動,在Counter.js就可以看到,由於redux-react-hooks提供了useMappedState及useDispatch,連線Counter的程式碼可以大大簡化。

import * as React from 'react';
import "./styles.css";
import {useMappedState,useDispatch} from 'redux-react-hook';

export default function Counter(props) {

    const counter = useMappedState(state=> state.counter);
    
    const dispatch = useDispatch();
    return (
        <div>
            <h1>
                Hello, {props.name}
                {counter} times
            </h1>
            <div>
                <button onClick={()=>dispatch({type:"INCREMENT"})}>Increment</button>
                <button onClick={()=>dispatch({type:"DECREMENT"})}>Decrement</button>
            </div>
        </div>
    );
}
複製程式碼

一個useMappedState,就扮演了mapStateToProps的角色,使用useDispatch,更可以直接於部件裡使用dispatch,無需任何特殊函式。其中一個更明顯的好處,在於Counter的props沒有依賴任何Redux的功能,因此要寫單元測試(Unit testing)就更為簡單。

Hooks程式碼總體上會簡潔很多!!可讀性也很樂觀

相關文章