react hook

Hook

可以让你在不编写class的情况下使用state以及其他React特性

Hook的作用就是让你的函数组件中可以使用class中的一些生命周期和state等。

Hook规则

Hook就是JavaScript函数,但是使用它们会有两个额外的规则

  • 只能在函数最外层调用Hook,不要在循环、条件判断或子函数中调用
  • 只能在React的函数组件中调用Hook。(除了自定义Hook外)

useState方法

基本例子

  • useState会返回一对值:当前状态和一个让你更新它的函数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    import React, { useState } from 'react';

    function Example() {
    // 声明一个叫 “count” 的 state 变量。
    // 这个变量的初始值是0, 即useState里的初始值
    // 更新这个变量的函数就是setCount
    const [count, setCount] = useState(0);

    return (
    <div>
    <p>You clicked {count} times</p>
    <button onClick={() => setCount(count + 1)}>
    Click me
    </button>
    </div>
    );
    }

useEffect

基本例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React, { useState, useEffect } from 'react';

function Example() {
const [count, setCount] = useState(0);

// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;
});

return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
  • useEffect默认在第一次渲染后和每次更新之后都会执行。 React保证了每次渲染effect的同时DOM都已经更新完毕。
  • componentDidMountcomponentDidUpdate不同的是,使用useEffect调度的effect不会阻塞浏览器更新屏幕,这让你的应用看起来响应更快。

清除effect

useEffect返回一个函数时,react将会在执行清除操作时调用它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...

useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}

ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);

// 返回一个函数,清除时调用。
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});

...

仅在state更改是更新。

使Hookcount更改时更新

1
2
3
useEffect(()=>{
document.title=`You clicked ${count} times`
},[count])

仅在 props.friend.id 发生变化时,重新订阅

1
2
3
4
5
6
7
8
9
10
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}

ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
}, [props.friend.id]);

useContext

1
2
// ./mycontext;
export const MyContext = React.createContext({count: 0})
1
2
3
4
5
6
// 在组件中使用
import { MyContext } from './mycontext';
const value = useContext(MyContext);

// 原来this.context.count;
// 相当于value.count

useReducer

1
2
3
4
const [state, dispatch] = useReducer(reducer, initialState, init);
// reducer: 形如(state,action) => newState;
// initialState:初始化的State
// init:惰性创建 state

基础例子

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
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();
}
}

function Counter({initialCount}) {
const [state, dispatch] = useReducer(reducer, initialCount, init);
return (
<>
Count: {state.count}
<button
onClick={() => dispatch({type: 'reset', payload: initialCount})}>

Reset
</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
</>
);
}

useRef

useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。

返回的 ref 对象在组件的整个生命周期内保持不变。

useRef不仅可以取代原来的ref属性,还可以用于保存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
30
31
// 用于普通ref
const domRef = useRef(null);

const onButtonClick = ()=>{
domRef.current.focus();
}

render(){
return(
<div>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</div>
)
}

// 用于保存一个实例变量

const staticRef = useRef(null);

useEffect(()=>{
const id = setInterval(() => {
// ...
});

// 这里staticRef就是用于保存变量的
staticRef.current = id;
return () => {
clearInterval(staticRef.current);
};
});

自定义Hook

自定义Hook是一个函数,其名称以use开头,函数内部可以调用其他Hook。

  • 两个组件中使用相同的Hook不会共享state,因为自定义 Hook 是一种重用状态逻辑的机制(例如设置为订阅并存储当前值),所以每次使用自定义 Hook 时,其中的所有stateeffect都是完全隔离的。
1
2
3
4
5
6
7
8
9
10
11
12
13

function Counter({initialCount}) {
const [count, setCount] = useState(initialCount);
return (
<>
Count: {count}
<button onClick={() => setCount(initialCount)}>Reset</button>
<button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
<button onClick={() => setCount(count + 1)}>+</button>
<button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
</>
);
}
-------------本文结束感谢您的阅读-------------