在项目中的更换 React Hooks 注意事项

3,110 阅读3分钟

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代码总体上会简洁很多!!可读性也很乐观