React Hook及自定义Hook 基本介绍
1.什么是Hook
Hook 是特殊的函数,只在 React渲染时有效。它们能让你 "hook" 到不同的 React 特性中去。我们可以通过hook把需要的状态、副作用方法钩进来,放在函数内部使用。让原本呆板的react函数拥有状态和生命周期。
2.useState 让函数拥有内部状态
组件通常需要根据交互更改屏幕上显示的内容。输入表单应该更新输入字段,当点击轮播图"下一个"应该更改显示的图片,或者点击一个按钮使一个显示的数字加一,都要使用到useState。
javascript
import { useState } from 'react'
// 状态:随着交互变化的数据
function App() {
const [count, setCount] = useState(0)
const handleClick = () => {
setCount(count + 1) // 把函数重新走一遍 有记忆功能 每次走一遍之后修改count的内容
}
return (
<>
<button onClick={handleClick}>点击</button>
{count}
</>
)
}
export default App
count
是一个state
变量,setCount
是对应的setter
函数,[..,..]
为数组结构,允许从数组中读取值,useState
的唯一参数是state
变量的初始值。在这个例子中,count
的变量是0。
State
是隔离且私有的,如果同一个组件被调用两次,两个副本之间是相互隔离的。
State
是一张快照 ,当状态放生更新时,编译器会对多次状态修改进行自动批处理 (React会等到事件处理函数中的所有代码都运行完毕之后再处理state更新,队列都执行完毕后,在进行UI更新),本例子中的count在按钮点击之后不会递增三次,由于快照尽管你调用了三次setCount(count + 1)
,但在这次渲染的事件处理函数中 number
会一直是0
javascript
import { useState } from 'react'
function App() {
let num = 0
const [count, setCount] = useState(0)
const handleClick = () => {
setCount(count + 1) //0 + 1
setCount(count + 1) //0 + 1
setCount(count + 1) //0 + 1
console.log(count)
}
console.log(count)
return (
<>
<button onClick={handleClick}>点击</button>
{count} {/* 渲染的是最后一次的结果 */}
</>
)
}
export default App
3.useEffect 让函数可以执行副作用
函数副作用是指函数在正常工作任务之外对外部环境所施加的影响。具体地说,函数副作用是指函数被调用,完成了函数既定的计算任务,但同时因为访问了外部数据,尤其是因为对外部数据进行了写操作,从而一定程度地改变了系统环境。函数的副作用也有可能是发生在函数运行期间,由于对外部数据的改变,导致了同步运行的外部函数受到影响。
javascript
import { useEffect, useState } from 'react' //声明
function App() {
const [count, setCount] = useState(0)
const handleClick = () => {
setCount(count + 1)
}
useEffect(() => {
console.log(count)
}, [count]) //count依赖项,只有count改变的时候才会触发
//当空数组的时候只有初始的时候会触发,更新的时候不会触发
useEffect(() => {
console.log(count)
}, [])
return (
<>
<button onClick={handleClick}>点击</button>
{count}
</>
)
}
export default App
useEffect
触发时机:jsx渲染完毕之后
useEffect
参数分为三种:
1.无参数useEffect(() => {console.log(count)})
初始时触发一次 当状态发生更新时再触发
2.空数组参数useEffect(() => {console.log(count)}, [])
只有初始的时候会触发 更新的时候不会触发
3.依赖项useEffect(() => {console.log(count)}, [count])
初始时触发一次 当依赖项发生改变时再触发
4.useContext 让函数可以深层传递参数
Context允许父组件向其下层无论多深的任何组件提供信息,而无需通过peops显示传递
javascript
import { createContext, useContext, useState } from 'react'
const Context = createContext(0)
function App() {
const [count, setCount] = useState(0)
const handleClick = () => {
setCount(count + 1)
}
return (
<>
<div>hello App</div>
<button onClick={handleClick}>点击</button>
<Context.Provider value={count}>
{/* 需要传递的参数 value 传入的参数可以是任何数据类型 */}
<Head />
</Context.Provider>
</>
)
}
function Head() {
return (
<>
<div>hello Head</div>
<Title />
</>
)
}
function Title() {
const value = useContext(Context) //在需要使用的组件中拿到数据
return (
<>
<div>hello Title</div>
{value}
</>
)
}
export default App
createContext(0)
括号中的0为初始值,当没有传递参数时得到的就是默认值
Countext
可以传递随着状态发生改变的值
5.useRef 可通过ref操作DOM
javascript
function App() {
const [count, setCount] = useState(0)
let num = useRef(0)
const handleClick = () => {
// 更行数据之后 函数回重新渲染 num会使用当前作用域下的值0 所以每次运行之后都是1 为了使num具有记忆功能 引入ref
setCount(count + 1)
num.current++
console.log(num.current)
}
return (
<>
<button onClick={handleClick}>点击</button>
{count}
</>
)
}
你可以用 ref.current
属性访问该 ref 的当前值
ref
再更改时不会触发重新渲染。 设置 state
会重新渲染组件,更改ref
不会!
你可以在渲染过程之外修改和更新current
的值 ,而对于state
,只能使用state
设置函数来修改state变量,从而排队重新渲染。可以把current
和state
搭配使用,这样就可以渲染出current
,如果只用ref
则不能实现current
修改后直接渲染出来。
javascript
//通过ref操作DOM
import { forwardRef, useRef, useState } from 'react'
//当组件添加ref属性的时候,需要forwardRef进行转发,forwardRef让你的组件通过ref向父组件公开DOM节点
const MyInput = forwardRef(function MyInput( ref) {
return (
<>
<input type="text" ref={ref} />
</>
)
})
function App() {
let ref = useRef(null)
const handleClick = () => {
ref.current.focus()
ref.current.style.background = 'yellow'
ref.current.value='123'
}
return (
<>
<button onClick={handleClick}>点击</button>
<MyInput ref={ref}/>
</>
)
}
export default App
由于 React
会自动处理更新DOM
以匹配你的渲染输出,因此你在组件中通常不需要操作DOM
。但是,有时你可能需要访问由 React
管理的 DOM
元素 ------ 例如,让一个节点获得焦点、滚动到它或测量它的尺寸和位置。在React
中没有内置的方法来做这些事情,所以你需要一个指向 DOM
节点的 ref
来实现。
当组件添加ref
属性的时候,需要forwardRef
进行转发,forwardRef
让你的组件通过ref
向父组件公开DOM
节点
6.什么是自定义HOOK
自定义hook是一个函数,函数内部可以调用其他hook函数,且以use开头命名,主要作用是对逻辑功能进行封装处理,达到一种复用能力
手动实现显示鼠标坐标的自定义hook
javascript
import { useEffect, useState } from 'react'
//实现一个实时获取鼠标的自定义Hook
function useMouse() {
const [state, setState] = useState({
pageX: NaN,
pageY: NaN,
})
useEffect(() => {
function move(e) {
setState({
pageX: e.pageX,
pageY: e.pageY,
})
}
// 创建事件
document.addEventListener('mousemove', move)
return () => {
//清理工作 删除事件
document.removeEventListener('mousemove', move)
}
}, [])
return state
}
function App() {
const mouse = useMouse()
return (
<>
<div>
{mouse.pageX} {mouse.pageY}
</div>
</>
)
}
export default App
第三方Hooks:ahooks react-use