0%

React Hooks小笔记

简介

React Hooks 是 React 16.7.0-alpha 版本推出的新特性,它主要目的是为了解决状态共享的问题。是继 render-propshigher-order components 之后的第三种状态共享方案,不会产生 JSX 嵌套地狱问题。

React Hooks 带来的好处不仅是 “更 FP,更新粒度更细,代码更清晰”,还有如下三个特性:

  1. 多个状态不会产生嵌套,写法还是平铺的(renderProps 可以通过 compose 解决,可不但使用略为繁琐,而且因为强制封装一个新对象而增加了实体数量)。
  2. Hooks 可以引用其他 Hooks。
  3. 更容易将组件的 UI 与状态分离。

在react-native的0.59.0中,即可支持react hooks的写法。

使用react hooks创建组件

在react native中创建一个组件大概如下

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
30
31
32
33
export default class App extends React.Component{
constructor(props) {
super(props);
this.state = {
number: 0,
};
}

componentDidMount() {
// 页面渲染之后执行
doSomethingA();
}

componentWillUnMount() {
// 页面卸载时执行
doSomethingB();
}

componentWillReceiveProps(nextProps: Props) {
// 页面接收到新参数
doSomethingC();
}

render() {
return (
<View>
<Text onPress={() => this.setState({ numer: this.state.number + 1 })}>
{this.state.number}
</Text>
</View>
);
}
}

而使用react hooks

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
import { useState, useEffect } from 'react';
const App = () => {
const [number, setNumber] = useState(0);
useEffect(() => {
// 页面渲染之后执行
doSomethingA();
return () => {
// 页面卸载时执行
doSomethingB();
}
}, []);

useEffect(() => {
// 页面接收到新参数
doSomethingC();
}, [number]);

return (
<View>
<Text onPress={() => setNumber(number + 1)}>
{number}
</Text>
</View>
);
}

由上述例子可见,使用了react hooks之后,组件由class变成了function。变得更加的轻量级,尤其是在创建无状态组件的时候,使用hooks更加具有优势,代码量减少。

Hooks API Reference

useState

1
2
import { useState } from 'react';
const [state, setState] = useState(initialState);

useState是可以看作是state与setState的替换,它返回有状态值,以及更新它的函数。在初始渲染期间,返回的状态(状态)与作为第一个参数(initialState)传递的值相同。而setState函数用于更新状态。 它接受一个新的状态值并将组件重新渲染。

1
setState(newState);

在后续重新渲染期间,useState返回的第一个值将始终是应用更新后的最新状态。

useEffect

1
2
import { useEffect } from 'react';
useEffect(didUpdate);

useEffect 的代码既会在初始化时候执行,也会在后续每次 rerender 时执行,而返回值在析构时执行。那么他就可以用来代替componentDidMount、componentWillReceiveProps以及componentWillUnmount三个生命周期。而且还支持第二个值来指定某些值作为useEffect的触发条件。

1
2
3
4
5
6
7
useEffect(() => {
const subscription = props.source.subscribe();
return () => {
// Clean up the subscription
subscription.unsubscribe();
};
}, []);

useContext

1
const value = useContext(MyContext);

接受上下文对象(从React.createContext返回的值)并返回该上下文的当前上下文值。 当前上下文值由树中调用组件上方最近的<MyContext.Provider>的值prop确定。

当组件上方最近的<MyContext.Provider>更新时,此Hook将触发重新呈现,并将最新的上下文值传递给该MyContext提供程序。

useContext的参数必须是上下文对象本身

useReducer

可以使用这个hook来实现一个redux机制

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
30
31
32
33
34
35
import { useReducer } from 'react';

function init(initialCount) {
return {count: initialCount};
}

function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
case 'reset':
return init(action.payload);
default:
throw new Error();
}
}

export default function App() {
const [state, dispatch] = useReducer(
reducer,
{count: 0},
);
return (
<View style={styles.container}>
<Text>Count: {state.count}</Text>
<Text onPress={() => dispatch({type: 'increment'})}>+</Text>
<Text onPress={() => dispatch({type: 'decrement'})}>-</Text>
<Text onPress={() => dispatch({type: 'reset', payload: 0})}>
Reset
</Text>
</View>
);
}

其它Hooks

除了以上提及的hooks,react还内置了其它的hooks,详情请参考Hooks API Reference

参考链接