几种常见的React Hooks
useState
useState,让函数组件拥有了维持状态的功能。维持状态是指在函数的多次渲染之间,这个state是可以在函数中间共享的
使用方式
import React, { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
return (
<div>
<p>{ count }</p>
<button onClick={() => setCount(count + 1)}>点击</button>
</div>
)
}
export default Counter
参数解析
useState(initialState)的参数initialState是state的初始值,可以是任意类型,如字符串、数值、布尔值、对象、数组
import React, { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
const [visible, setVisible] = useState(false);
const [store, setStore] = useState({});
const [list, setList] = useState([]);
const [name, setName] = useState('xcc');
return ...
}
export default Counter
useState()返回值是一个包含两个元素的数组,第一个值为state的值,为只读的,第二个是用来设置state值的
对比类组件
类组件只有一个state,通过通过对象中的不同属性来表示不同的状态,通过setState来进行更新。函数组件可以创建多个state,用来描述不同状态的值,更加语义化
类组件:
import React from 'react'
class Counter extends Component {
constructor(props) {
super(props)
this.state = {
count: 0,
visible: false
}
}
componentDidMount() {
setState({ count: 1 })
}
render() {
...
}
}
export default Counter
函数组件:
import React, { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
const [visible, setVisible] = useState(false);
return ...
}
export default Counter
使用时需要注意的点
不要在state中存储可以通过计算得到的值
常见情况:
- props中传递过来的值
- 存储在cookie、localStorage中的值
- 挂载在URL参数上的值
useEffect
useEffect,用来执行一段副作用,副作用是指一段和当前执行结果无关的代码。其中代码的执行是不会影响UI的渲染
使用方式
import React, { useState, useEffect } from 'react'
const WindowSize = () => {
const [size, setSize] = useState(null)
useEffect(() => {
const handleResize = () => {
...
}
window.addEventListener("resize", handleResize)
return () => {
window.removeEventListener("resize", handleResize)
}
}, [])
return (
...
)
}
export default WindowSize
参数解析
useEffect(callback, dependencies)
callback为要执行的函数,dependencies为可选的依赖项数组
几种常见的使用方式:
没有依赖项时,会在每次render后执行
useEffect(() => {})
依赖项为空数组时,会在首次render后执行
useEffect(() => {}, [])
依赖项不为空时,会在首次render后,每次依赖项数组发生改变时执行
useEffect(() => {}, [a,b,c])
组件在卸载时执行
useEffect(() => { return () => {} }, [])
对比类组件
useEffect想比类组件的生命周期,基本可以等价于ComponentDidMount、componentDidUpdate 和 componentWillUnmount这三个方法,但有不是完全相同
类组件
import React from 'react'
class WindowSize extends Component {
constructor(props) {
super(props)
this.state = {
size: null
}
}
componentDidMount() {
window.addEventListener("resize", this.handleResize)
}
componentWillUnmount() {
window.removeEventListener("resize", this.handleResize)
}
handleResize = () => {
...
}
render() {
...
}
}
export default WindowSize
函数组件:
import React, { useState, useEffect } from 'react'
const WindowSize = () => {
const [size, setSize] = useState(null)
useEffect(() => {
const handleResize = () => {
...
}
// 等价于类组件中的componentDidMount
window.addEventListener("resize", handleResize)
// 等价于类组件中的componentWillUnmount
return () => {
window.removeEventListener("resize", handleResize)
}
}, [])
return (
...
)
}
export default WindowSize
使用时注意的点
依赖项一定要为回调函数中在使用的变量
import React, { useState, useEffect } from 'react'
const Books = ({ id }) => {
const [list, setList] = useState([])
useEffect(() => {
const getList = async () => {
const res = await getBookList({ id })
setList(res.data)
}
getList()
}, [id])
return ...
}
export defaule Books;
依赖项要为一个常量数组,而不是一个动态数据
useEffect(() => {}, [id])
React会使用浅比较来对比依赖项是否发生改变,因此不要使用对象、数组等作为依赖项
function Todos() {
// 这里在每次组件执行时创建了一个新数组
const todos = [{ text: 'Learn hooks.'}];
useEffect(() => {
console.log('Todos changed.');
}, [todos]);
}