继上次分享了React新特性,当然参考了论坛中一些人的看法,在社区中,大部分布道者都提到了诸如“过于冗繁的组件嵌套”、“与内部原理的更亲密接触”、“比原先更细粒度的逻辑组织与复用”等优势,这次来谈下对于新特性中的hooks的看法。
React新特性中的hooks强调了用函数式组件的思想来代替类组件,然而这个也颠覆了react中原本函数式组件的写法。
1 | function TextComponent(text){ |
上例代码是一个非常简单的函数组件,只依赖入参。
1 | function TextComponent(){ |
上例代码是用了hooks的一个函数组件。
虽然在功能上两种写法是一致,但是可以看出hooks的组件并不是纯粹的输入到输出
,而是变成了changeText
方法控制的输出,text是依赖changeText方法的。也就是说对于函数组件来说更多地去依赖了changeText方法这一逻辑控制。
在这里我们可以先讨论下关于类组件和函数组件。
某些情况下函数组件可以直接代替类组件,但函数组件和类组件之间最大的区别就是一个有状态机制,一个没有状态机制。函数组价没有内部状态变化机制,只能从外部进行状态的驱动。
1 | function Hello(props, context) { |
1 | class Hello extends Component { |
状态机制的存在使得函数组件无法取代类组件,因此我们写代码的时候更多的都是去写类组件。
但类组件也有很多不足之处。
标签嵌套地狱
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17render() {
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
29import { 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
22let { 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
8function Hello(props){
return <p>Hello {props.name}</p>
}
function useHello(){
let [hello,setHello] = useState('hello');
return [hello,setHello];
}