Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
Hooks 的本质:一套能够使函数组件更强大,更灵活的“钩子”。
注意点:
- 有了 hooks 之后,为了兼容老版本,class 类组件并没有被移除,俩者都可以使用;
- 有了 hooks 之后,不能再把函数组件称为无状态组件了,因为 hooks 为函数组件提供了状态;
- hooks 只能在函数组件中使用。
useState
useState 为函数组件提供状态(state)
使用步骤
代码实现
// 从 react 中解构出 useState
import { useState } from 'react'
function App () {
// 调用 useState 函数,并传入状态的初始值
const [count, addCount] = useState(0)
// 这里的 count 是状态,addCount 是更新状态的方法
return (
<div className="App">
<p>count: {count}</p>
{/* 通过点击按钮调用修改状态的方法更新状态 */}
<button onClick={() => addCount(count + 1)}>count+1</button>
</div>
)
}
修改状态
使用规则
1.useState
函数可以执行多次,每次执行互相独立,每调用一次为函数组件提供一个状态;
function List(){
// 以字符串为初始值
const [name, setName] = useState('zs')
// 以数组为初始值
const [list,setList] = useState([])
}
2. const [状态, 更新状态的方法] = useState(初始值),注:这里的“初始值”可以是一个函数(只要函数 return 一个值就行),所以,如果初始值是需要通过一定的逻辑(比如计算)才能得到,可以写一个方法,让该方法 return 初始值即可;
3.useState
注意事项
- useState 提供的状态是函数内部的局部变量,可以在函数内的任意位置使用;
- useState 的初始值(参数)只会在组件第一次渲染时生效。也就是说,以后的每次渲染,useState 获取到都是最新的状态值,React 组件会记住每次最新的状态值;
- 调用 useState() 的语句只能出现在函数组件或者其他 hook 函数中;
- 不能嵌套在 if/for/ 其它函数中(react 按照 hooks 的调用顺序识别每一个 hook )
useEffect
useEffect 可以让你在函数组件中执行副作用操作
什么是副作用
副作用是相对于主作用来说的,一个函数除了主作用,其他的作用就是副作用。对于 React 组件来说,主作用就是根据数据(state/props)渲染 UI,除此之外都是副作用(比如,手动修改 DOM)
常见的副作用
- 数据请求 ajax 发送
- 手动修改 dom
- localstorage 操作
使用步骤
代码实现
import { useEffect, useState } from 'react'
function App() {
const [count, setCount] = useState(0)
useEffect(()=>{
// dom操作
document.title = `当前已点击了${count}次`
})
return (
<button onClick={() => { setCount(count + 1) }}>{count}</button>
)
}
export default App
useEffect()
依赖项控制执行时机
1. 不添加依赖项
组件首次渲染执行一次,以及不管是哪个状态更改引起组件更新时都会重新执行
- 组件初始渲染
- 组件更新 (不管是哪个状态引起的更新)
// 默认无依赖项的写法:
useEffect(() => {
document.title = count
}) // <--注意这里
2. 添加空数组
组件只在首次渲染时执行一次
// 空数组依赖项的写法:函数体中不能使用状态
useEffect(() => {
document.title = 1
}, []) // <--注意这里
3. 添加特定依赖项
副作用函数在首次渲染时执行,在依赖项发生变化时重新执行(多个依赖项时为“或”关系)
// 依赖特定项的写法:
useEffect(() => {
document.title = count
}, [count]) // <--注意这里,如果数组中有多个值,则任一值发生变化均会触发此函数执行
注意事项
useEffect 回调函数中用到的数据(比如,count)就是依赖数据,就应该出现在依赖项数组中,如果不添加依赖项就会有 bug 出现
清理副作用
如果想要清理副作用 可以在副作用函数中的末尾 return 一个新的函数,在新的函数中编写清理副作用的逻辑
注意执行时机为:
const App = () => {
const [count, setCount] = useState(0)
useEffect(() => {
const timerId = setInterval(() => {
setCount(count + 1)
}, 1000)
return () => {
// 用来清理副作用的事情
clearInterval(timerId)
}
}, [count])
return (
<div>
{count}
</div>
)
}
注:如果使用 useEffect() 发送网络请求,并且使用 async/await 时,不可以直接在 useEffect 的回调函数外层直接包裹 async ,因为异步会导致函数无法立即返回,正确写法应该在内部单独定义一个函数,然后把这个函数包装成同步。示例如下:
useEffect(()=>{
// 注意:要在内部再定义一个函数才可以使用 async/await 修饰
async function fetchData(){
const res = await axios.get('http:/XXX.net/api/getData')
console.log(res)
}
},[])
useRef
使用步骤
代码实现
import React, { useEffect, useRef } from 'react'
// useRef 的使用:函数组件由于没有实例,不能使用ref获取,如果想获取组件实例,必须是类组件
class Test extends React.Component {
render () {
return (
<div>这是Test组件</div>
)
}
}
function App () {
const testRef = useRef(null)
const h1Ref = useRef(null)
useEffect(() => {
// 这里拿到的是组件示例所以可以直接访问组件内部的状态、方法
console.log(testRef.current)
console.log(h1Ref.current)
// 注:useEffect 的回调是在 DOM 渲染完成后执行的,所以能拿到 DOM 元素
})
return (
<div className="App">
<Test ref={testRef} />
<h1 ref={h1Ref}>App</h1>
</div>
)
}
export default App
useContext
实现步骤
代码实现
import React, { useState, createContext, useContext } from 'react'
const Context = createContext()
// 子组件
function ComA () {
// 获取上层组件传递的数据
const count = useContext(Context)
return (
<div style={{ border: '1px solid red' }}>这里是ComA组件,count: {count}
<br />
<ComC />
</div>
)
}
// 孙组件
function ComC () {
// 获取上层组件传递的数据
const count = useContext(Context)
return (
<div style={{ backgroundColor: 'skyblue' }}>这里是ComC组件,count: {count}</div>
)
}
function App () {
const [count, setCount] = useState(20)
return (
// 提供数据,固定写法,使用 Provider 节点包裹,然后使用 vaule 传值
<Context.Provider value={count}>
<div className="App">
这里是App组件,count: {count}
<ComA />
{/* 在父组件中修改了 count 子孙组件中使用的 count 也会同步更新 */}
<p><button onClick={() => setCount(count + 1)}>count+1</button></p>
</div>
</Context.Provider>
)
}
export default App
更多 hooks 详细知识-官网直达。
原文地址:https://www.jb51.cc/wenti/3280318.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。