三个常用hook
Hook 是 React 16.8.0 增加的新特性,让我们能在函数式组件中使用
state
和其他特性
1. State Hook
(1)State Hook
让函数式组件也可可以有state
状态,并进行状态数据的读写(2)语法:
const [xxx, setXxx] = React.useState(initValue)
initValue
为状态初始化值,第一次初始化指定的值在内部做缓存- 返回值
xxx, setXxx,
包含 2 个元素的数组,分别为当前状态值和状态更新函数
(3)setXxx()
的 2 种用法:
setXxx(newValue)参数为非函数值,直接指定新的状态值,内部用其覆盖原来的状态值
setXxx(value => newValue)参数为函数,接受原本的状态值,返回新的状态值,内部用其覆盖原来的状态值
注意!若有多个状态,只能多次调用
React.useState
,不能使用对象!点我加1 案例:
import { useState } from "react"; export default function Demo(props) { const [count, setCount] = useState("0") function addOne { setCount(count + 1) #第一种写法 # setCount(count=>count+1) #第二种写法 } return ( <div> <h2>求和为{count}</h2> <button onClick={addOne}>点我加1</button> </div> ) }
(1) 点击button ,会调用addOne函数,然后调用更新状态函数,然后Demo函数式组件重新执行渲染,这会导致const [count, setCount] = useState("0") 这句代码执行,每次点击button都会让执行此句代码。react底层做了处理,不会因为每次更新都执行这句代码导致重新初始化状态。而是保留上次的状态值。
(2)()=>{} 箭头函数 如果单个参数,可以省略括号,如果就一行返回值代码,可以省略return。如果返回的是对象 需要写小括号({}),防止和代码段的{}混淆。
2. Effect Hook 副作用钩子,模拟生命周期
Effect Hook
让我们能在函数式组件中执行副作用操作(就是模拟生命周期钩子)- 副作用操作
- 发送 Ajax 请求
- 定时器
- 手动更改真实 DOM 。react原则上尽量不操作dom,所以此处尽量不做。
useEffect
可以模拟三个生命周期:componentDidMount
、componentDidUpdate
、componentWillUnmount
React.useEffect
第一个参数如果return
一个函数,那么此函数相当于componentWillUnmount
,若有useEffect多次调用,多次return一个函数,那么多个函数会按先后顺序依次执行。
用法
- useEffect语法
React.useEffect(() => { ... //此处写的代码,会在特定时机执行 return () => { // 组件卸载前执行,即 componentWillUnmount 钩子 ... //在此做一些收尾工作 比如清除定时器、取消订阅等 } }, [stateValue]) //如果stateValue是[],回调函数只会在第一次render后执行
(1)不写第二个参数
监听全部状态。若第二个参数不写,表示监听所有状态的更新。每次更新任何一个状态,都会执行。类似于componentDidMount、
componentDidUpdate两个组合。
React.useEffect(() => { console.log('All DidUpdate') })
(2) 写第二个参数
第二个参数数组为空数组[]
第二个参数数组为空数组[],表示不监听任何状态的更新,因此只有页面首次加载完成时渲染会执行,类似于componentDidMount。import React from "react" const [count, setCount] = React.useState(0) React.useEffect( () => { setInterval(() => setCount(count=> count + 1), 1000) } , [])
第二个数组参数为状态名
监听部分状态。第二个参数数组写上状态名字,表示只监听这些状态的更新。也是类似于componentDidMount、
componentDidUpdate两个组合。
React.useEffect(() => { console.log('Part DidUpdate') }, [count, name])
定时器清除
如果开启了定时器,那么需要在卸载dom时清除定时器
let target = setInterval(()=>{},ms) //componentDidMount启用定时器 clearInterval(target) //componentWillUnMount清除定时器
如果不清除会报错
import React from "react" import ReactDOM from "react-dom" export default function Demo(props) { const [count, setCount] = React.useState(0) React.useEffect( () => { console.log("adfa"); let timer = setInterval(() => setCount(count => count + 1), 1000) return ()=>{ clearInterval(timer) } } , [] ) function unmount() { ReactDOM.unmountComponentAtNode(document.getElementById("root")) } return ( <div> <h2>求和为{count}</h2> <button onClick={unmount}>卸载组件</button> </div> ) }
3. Ref Hook
Ref Hook
可以在函数式组件存储或查找组件内的标签或其他数据- 语法:
const refContainer = React.useRef()
- 保存标签对象的容器,和
React.createRef()
类似,也是专人专用,多个标签必须多个createRefimport React from "react" function Demo() { const myRef = React.useRef() function show() { console.log(myRef.current.value) } return ( <div> <input type="text" ref={myRef} /> <button onClick={show}>展示数据</button> </div> ) }