「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战」
【前情】在 class 组件中使用 state
class Layout extends React.Component {
state = {
loading: true
}
componentDidMount() {
this.setState({ loading: false })
}
render() {
const { loading } = this.state;
const { children, isLogin } = this.props;
if (!isLogin || loading) {
return (
<div>loading...</div>
)
}
return ( children )
}
}
使用 hook
实现在不编写 class 组件 的情况下使用
state以及其他react特性
一个组件中多次调用
useStateanduseEffect,是完全独立的
useState
在函数组中修改组件状态。具体说明参考:【React初接触】(二)粗了解State和prop
const [state, setState] = useState(initialVal);
import { useState } from 'react';
export default (props?: any) => {
// useState 传入初始state参数,返回当前 state 和 更新state的函数
const [count, setCount] = useState(() => {
return someExpensiveComputation(initialCount);
})
return (
Count: {count}
// 传参形式一:setCount 传入更新值
<button onClick={() => { setCount(initialCount) }}>reset</button>
// 传参形式二:setCount 传入函数
<button onClick={() => setCount(preCount => preCount - 1)}> - </button>
<button onClick={() => setCount(preCount => preCount + 1)}> + </button>
)
}
useEffect
副作用操作:数据获取、设置订阅、手动更改
React组件中的DOM
useEffect(didUpdate)
在 react更新 DOM 之后运行一些额外的代码,通过这个hook 告知组件操作内容。React 会保存这个函数(effect),并在执行 DOM 更新之后调用。
- 执行时机:
-
默认情况: 第一次渲染之后 和 每次更新之后 都会执行(保证每次执行,DOM都已经更新完成,即在浏览器完成布局和绘制之后)。
-
条件执行: 给
useEffect传递第二个参数,作为依赖值数组,其中任意项变化都将触发函数调用p.s. 确保数组包含所有外部作用域中会随时间变化并且在effect中使用的变量,否则代码会引入之前的变量。
-
特殊用法: 当
useEffect第二个参数是空数组时,将只在组件挂载和卸载时执行一次effect不依赖props或state,故不需要重复执行。
// 仅在count更改时更新
useEffect(() => {
document.title = `you click ${count} times`;
}, [count])
// 仅在组件挂载时更新
useEffect(() => {
document.title = `you click ${count} times`;
}, [])
- 清除:
-
无需清除的
effect -
需要清除的
effect:返回清除函数,将在下一个effect执行之前清除上一个
使用 useEffect 解决一个常见报错
Warning: Can't perform a React state update on an unmounted component.
This is a no-op, but it indicates a memory leak in your application.
To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
解决方法:在组件未渲染时操作state产生报错(常见于setTimeout操作等)
- class组件使用
componentWillUnmount
componentWillUnmount(){
clearTimeout(id)
}
- useEffect传入清除函数
const [isOnline, setIsOnline] = useState(null)
useEffect(() => {
const id = setTimeout(() => {...})
return () => {
clearTimeout(id)
}
}