之前学习hooks时根据官方例子整理的简单用法
HOOK的规则
-
只在最顶层使用hook
-
只在react函数中调用hook,不要在普通js函数中调用(在自定义hook中调用hook)
那么 React 怎么知道哪个 state 对应哪个 useState? 答案是 React 靠的是 Hook 调用的顺序。 因为我们的示例中,Hook 的调用顺序在每次渲染中都是相同的, 所以它能够正常工作
useEffect的基础语法
import React, { useEffect } from 'react';
//useEffect是在页面渲染完成后执行的
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;
}
Effect Hook 可以在函数组件中执行副作用操作
- 在react的class组件中,render函数是不应该有任何副作用的,在这里执行操作太早了,应该在更新dom之后才执行我们的操作
- class中把副作用放在componentDidMount和componentDidUpdata函数中,相当于函数组件的useEffect
在这里useEffect做了什么呢
- 告诉react组件需要在渲染后执行某些操作,react会保存你传递的函数(effect),在执行dom更新之后调用他。
- 为什么在组件内部调用useEffect,放在组件内部方便访问state变量或者其他props。
- useEffect在每次渲染之后都会执行,react保证每次运行effect的同时,dom都已经更新完毕。
需要清除的effect
在react class中,在componentDidMount中设置订阅,
在componentWillUnmount中清除他,在effect中订阅和清除是在同一个地方执行
effect返回一个函数时,react在执行清除操作时会调用它
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);
// Specify how to clean up after this effect:
return function cleanup() {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
- react会在组件卸载时执行清除操作,不需要清除的直接写不需要返回,需要清除的动作写在返回函数里面。
- 可以使用多个effect,就像state的hook一样,写多个useEffect,将多个不相关的逻辑分离到不同的effect中。
useEffect的第二个参数
- 传递数组作为第二个可选参数,假设第二个参数值和要更新的数据相同则跳过effect的调用。实现性能优化
- 如果数组中有多个元素,即使只有一个元素发生变化,也会调用effect
- 对于有清除函数的effect同样适用,仅在第二个参数发生变化时重新订阅。
- 注意:使用此方法时,确保数组中包含了外部作用域中会随时间变化并且在effect中使用的变量。
- 如果想只执行一次effct,可以传递一个空数组