react-Hook
React-Hook
目的
React Hooks 要解决的问题是状态共享,不会产生 JSX 嵌套地狱问题。
设计目的,就是加强版函数组件,完全不使用"类",就能写出一个全功能的组件。
基础 Hook
1.useState
const [state, setState] = useState(initialState);
返回一个 state,以及更新 state 的函数。
在初始渲染期间,返回的状态 (state) 与传入的第一个参数 (initialState) 值相同。
setState 函数用于更新 state。它接收一个新的 state 值并将组件的一次重新渲染加入队列
后续的重新渲染中,useState 返回的第一个值将始终是更新后最新的 state
2.useEffect
useEffect(didUpdate);
接收一个包含命令式、且可能有副作用代码的函数,使用 useEffect 完成副作用操作。赋值给 useEffect 的函数会在组件渲染到屏幕之后执行。
清除 effect需返回一个清除函数。
注意:在函数组件主体内(这里指在 React 渲染阶段)改变 DOM、添加订阅、设置定时器、记录日志以及执行其他包含副作用的操作都是不被允许的,因为这可能会产生莫名其妙的 bug 并破坏 UI 的一致性。
3.useContext
额外的 Hook
useReducer
useCallback
useMemo
useRef
useImperativeHandle
useLayoutEffect
useDebugValue
State Hook
useState 是允许在 React 函数组件中添加 state的钩子函数
在编写函数组件时,需要向其添加一些 state,就用useState
import React, { useState } from 'react';
function Example() {
// 声明一个叫 "count" 的 state 变量,传 0 作为变量的初始 state
// 返回值为:当前 state 以及更新 state 的函数
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
// 当用户点击按钮后,我们传递一个新的值给 setCount。React 会重新渲染 Example 组件,并把最新的 count 传给它
Click me
</button>
</div>
);
}
对比class
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
Effect Hook
Effect Hook 可以让你在函数组件中执行副作用操作(数据获取,设置订阅以及手动更改 React 组件中的 DOM )
不用清除的effect
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// 告诉 React 组件需要在渲染后执行某些操作
useEffect(() => {
// useEffect 放在组件内部让我们可以在 effect 中直接访问 count state 变量(或其他 props)
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
需要清除的effect
effect 在每次渲染的时候都会执行,React 会在执行当前 effect 之前对上一个 effect 进行清除
import React, { useState, useEffect } from 'react';
function FriendStatus(props) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
// React 会在组件卸载的时候执行清除操作
return function cleanup() {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
Hook规则
只在最顶层使用 Hook
确保 Hook 在每一次渲染中都按照同样的顺序被调用。这让 React 能够在多次的 useState 和 useEffect 调用之间保持 hook 状态的正确
只在 React 函数中调用 Hook
在函数组件或自定义Hook中调用,保证代码逻辑清晰可见
自定义 Hook
组件之间共享逻辑时,要提取都第三个函数中。
每次调用 Hook,它都会获取独立的 state
function FriendStatus(props) {
const isOnline = useFriendStatus(props.friend.id);
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
function FriendListItem(props) {
const isOnline = useFriendStatus(props.friend.id);
return (
<li style={{ color: isOnline ? 'green' : 'black' }}>
{props.friend.name}
</li>
);
}