简介
Hooks 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
Hooks 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。
优点
(1)Hooks 将组件中相互关联的部分拆分成更小的函数(比如设置订阅或请求数据),无需强制按照生命周期划分。
(2)Hooks 使你在无需修改组件结构的情况下复用状态逻辑。
(3)Hooks 使你在非 class 的情况下可以使用更多的 React 特性,Hooks 转向函数,但仍继续为 class 组件提供支持。
Hooks 使用规则
Hooks 就是 JavaScript 函数,但是使用它们会有两个额外的规则:
- 只能在函数最外层调用 Hooks。不要在循环、条件判断或者子函数中调用。
- 只能在 React 的函数组件和自定义的 Hooks 中调用 Hooks。不要在其他 JavaScript 函数中调用。
State Hook
当我们使用 useState 定义 state 变量时候,它返回一个有两个值的数组。第一个值是当前的 state,第二个值是更新 state 的函数。
import React, { useState } from 'react';
function Example() {
// 声明多个 state 变量!
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
// ...
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
Effect Hook
useEffect 就是一个 Effect Hook,给函数组件增加了操作副作用的能力(数据获取,设置订阅以及手动更改 React 组件中的 DOM 都属于副作用)。它跟 class 组件中的 componentDidMount、componentDidUpdate 和componentWillUnmount 具有相同的用途,只不过被合并成了一个 API。
effect 发生在“渲染之后”,不用再去考虑“挂载”还是“更新”。默认情况下,React 会在每次渲染后调用副作用函数 —— 包括第一次渲染的时候。由于副作用函数是在组件内声明的,所以它们可以访问到组件的 props 和 state。
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
- 需要清除的 effect
例如订阅外部数据源。这种情况下,清除工作是非常重要的,可以防止引起内存泄露!副作用函数还可以通过返回一个函数来指定如何“清除”副作用。
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
React 将按照 effect 声明的顺序依次调用组件中的每一个 effect。
- 通过跳过 Effect 进行性能优化
如果某些特定值在两次重渲染之间没有发生变化,你可以通知 React 跳过对 effect 的调用,只要传递数组作为 useEffect 的第二个可选参数即可:
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // 仅在 count 更改时更新,此处做全等对比
useContext
useContext
让你不使用组件嵌套就可以订阅 React 的 Context。
接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。
useMemo
把“创建”函数和依赖项数组作为参数传入 useMemo,它仅会在某个依赖项改变时才重新计算 memoized 值。这种优化有助于避免在每次渲染时都进行高开销的计算。返回一个 memoized 值。
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
记住,传入 useMemo 的函数会在渲染期间执行。请不要在这个函数内部执行与渲染无关的操作,诸如副作用这类的操作属于 useEffect 的适用范畴,而不是 useMemo。
useRef
一个常见的用例便是命令式地访问子组件:
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` 指向已挂载到 DOM 上的文本输入元素
inputEl.current.focus();
};
return (
<div>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</div>
);
}
网友评论