React Hooks看法

继上次分享了React新特性,当然参考了论坛中一些人的看法,在社区中,大部分布道者都提到了诸如“过于冗繁的组件嵌套”、“与内部原理的更亲密接触”、“比原先更细粒度的逻辑组织与复用”等优势,这次来谈下对于新特性中的hooks的看法。

React新特性中的hooks强调了用函数式组件的思想来代替类组件,然而这个也颠覆了react中原本函数式组件的写法。

1
2
3
function TextComponent(text){
return <p>{text}</p>
}

上例代码是一个非常简单的函数组件,只依赖入参。

1
2
3
4
function TextComponent(){
let [text,changeText] = useState('hello');
return <p>{text}</p>
}

上例代码是用了hooks的一个函数组件。
虽然在功能上两种写法是一致,但是可以看出hooks的组件并不是纯粹的输入到输出,而是变成了changeText方法控制的输出,text是依赖changeText方法的。也就是说对于函数组件来说更多地去依赖了changeText方法这一逻辑控制。

在这里我们可以先讨论下关于类组件和函数组件。

某些情况下函数组件可以直接代替类组件,但函数组件和类组件之间最大的区别就是一个有状态机制,一个没有状态机制。函数组价没有内部状态变化机制,只能从外部进行状态的驱动。

1
2
3
function Hello(props, context) {
return <span>Hello {props.name}</span>
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Hello extends Component {
state = {
name: 'haha'
};

handleClick=()=>{
this.setState({
name: 'hehe'
});
}
render() {
return <span onClick={this.handleClick}>Hello {this.state.name}</span>
}
}

状态机制的存在使得函数组件无法取代类组件,因此我们写代码的时候更多的都是去写类组件。
但类组件也有很多不足之处。

  • 标签嵌套地狱

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    render() {
    return (
    <FooContext.Provider value={this.state.foo}>
    <BarContext.Provider value={this.state.bar}>
    <BarContext.Consumer>
    {bar => (
    <FooContext.Consumer>
    {foo => (
    console.log(bar, foo)
    )}
    </FooContext.Consumer>
    )}
    </BarContext.Consumer>
    </BarContext.Provider>
    </FooContext.Provider>
    )
    }
  • 一些有状态的逻辑比较难重用,需要大量借助Context

其实这个也是react的不足之处,因此React团队基于函数组件提出hooks的概念。

以上的例子可以综合成下面这个hook例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import { useState, useContext, useEffect, createContext } from 'react';
const FooContext = createContext('foo');
const BarContext = createContext('bar');

function Hello(props, context) {
const [name, setName] = useState('haha');

const foo = useContext(FooContext);
const bar = useContext(BarContext);

const handleClick = () => setName('hehe');

useEffect(() => {
return () => {
}
}, [name]);

return (
<>
<span onClick={handleClick}>Hello {name}</span>

<FooContext.Provider>
<BarContext.Provider>
{foo}, {bar}
</BarContext.Provider>
</FooContext.Provider>
</>
)
}

从上面其实可以看出一些react团队的编码思想。

  • let [text,changeText] = useState('hello')这种写法可以让状态和逻辑两两配对,并且因为使用者可以用useState自定义各种hooks,所以可以让开发者更好地处理代码结构;
  • 状态的颗粒度可以很小,由于配对的原因可控范围也很小,对于整体的影响范围不大,单个组件中能用多个hook来进行状态修改,甚至可以拆分成多个组件或状态;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    let { useState, useEffect } = require('react');

    function useIsHear() {
    let [isHear, setIsHear] = useState(false);

    function isHearChange() {
    setIsHear(true);
    }

    useEffect(() => {
    isHearChange()
    return () => {
    };
    }, [isHear]);

    return isHear;
    }

    function Answer() {
    let isHear = useIsHear();
    return {isHear ? <span>answer</span>:<span>leave</span>}
    }

通过hooks可以方便的把状态进行分离,每一个状态分离后可复用,通过组合的方式提供一种有状态逻辑的复用。

  • 通过hooks更容易实现逻辑与展示的分离,函数组件依然会是一个实现渲染逻辑的纯组件,对状态的管理已经被hooks内部所实现,即有状态无渲染和有渲染无状态;
    1
    2
    3
    4
    5
    6
    7
    8
    function Hello(props){
    return <p>Hello {props.name}</p>
    }

    function useHello(){
    let [hello,setHello] = useState('hello');
    return [hello,setHello];
    }
觉得不错的话可以打赏哦