为什么要有Hook
本质:让函数组件可以拥有状态
useState
基础使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import { useState } from 'react'
function App () {
const [count, setCount] = useState(0) return ( <button onClick={() => { setCount(count + 1) }} >{count}</button> ) }
export default App
|
- 在修改状态时,一定要用新值代替旧值而不是直接修改,尤其是引用类型
- useState函数多次执行相互独立,每次调用为函数组件提供一个状态
- useState不能嵌套在for/if/其他函数中,因为react按照hook调用顺序识别每个hook
回调函数作为状态参数
回调函数return出去的值将作为初始值,只在渲染组件时执行该回调函数
这样可以根据传参提供不同的初始值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import { useState } from 'react'
function Counter (props) { const [count, setCount] = useState(() => { return props.count }) return ( <button onClick={() => { setCount(count + 1) }} >{count}</button> ) }
function App () { return ( <> <Counter count={10} /> <Counter count={20} /> </> ) }
export default App
|
useEffect
为react函数提供副作用处理 (主作用指根据数据渲染UI,其余都属于副作用,常见副作用有手动修改dom,数据请求,localstorage修改等)
基础使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import { useEffect, useState } from 'react'
function App () { const [count, setCount] = useState(0) useEffect(() => { document.title = `当前点击了${count}次` }) return ( <button onClick={() => { setCount(count + 1) }} >{count}</button> ) }
export default App
|
useEffect依赖项
基础使用中是不添加依赖项的情况,在组件初始渲染和任何状态改变导致的组件更新时都会执行
当我们添加空数组的时候,表示只在初始渲染的时候执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import { useEffect, useState } from 'react'
function App () { const [count, setCount] = useState(0) useEffect(() => { document.title = `当前点击了${count}次` }, []) return ( <button onClick={() => { setCount(count + 1) }} >{count}</button> ) }
export default App
|
当我们在数组中添加依赖项时,只有依赖项改变才会执行useEffect
1 2 3
| useEffect(() => { document.title = `当前点击了${count}次` }, [count])
|
useEffect清理副作用
有时候useEffect中的副作用操作是需要被清理的,比如计时器操作,如下代码所示,如果没有副作用清理操作,当组件被删除的时候计时器仍在运行,可以在console中看到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import { useEffect, useState } from 'react'
function Test () { useEffect(() => { setInterval(() => { console.log('计时器运行中') }, 1000) }) return <div>Test</div> }
function App () { const [flag, setFlag] = useState(true) return ( <> <button onClick={() => setFlag(false)}>delete</button> {flag ? <Test /> : null} </> ) }
export default App
|
useEffect清理副作用的操作流程一般如下所示
1 2 3 4 5 6 7 8 9 10
| useEffect(() => {
return () => {
} })
|
对于之前的计时器代码的清理副作用操作如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import { useEffect, useState } from 'react'
function Test () { useEffect(() => { const timeId = setInterval(() => { console.log('计时器运行中') }, 1000) return () => { clearInterval(timeId) } }) return <div>Test</div> }
function App () { const [flag, setFlag] = useState(true) return ( <> <button onClick={() => setFlag(false)}>delete</button> {flag ? <Test /> : null} </> ) }
export default App
|
useRef
用于获取绑定dom对象或是组件对象
获取dom
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import { useEffect, useRef } from 'react'
function App () { const testRef = useRef(null) useEffect(() => { console.log(testRef) }, [testRef]) return ( {} <> <h1 ref={testRef}>hello world</h1> </> ) }
export default App
|
获取组件
1 2 3 4 5 6 7 8
| class Foo extends React.Component { render(){ return <div>Foo</div> } }
export default Foo
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| import { useEffect, useRef } from 'react' import Foo from './Foo' function App() { const h1Foo = useRef(null) useEffect(() => { console.log(h1Foo) }, []) return ( <div> <Foo ref={ h1Foo } /></div> ) } export default App
|
useContext
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| import { createContext, useContext } from 'react'
const Context = createContext()
function Foo () { return <div>Foo <Bar /></div> }
function Bar () { const { name, list } = useContext(Context) return <div>Bar {name} {list}</div> }
const name = 'this is name' const list = [1, 2, 3]
const value = { name, list }
function App () { return ( <Context.Provider value={value}> <div><Foo /></div> </Context.Provider> ) }
export default App
|