Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
Hooks 的本质:一套能够使函数组件更强大,更灵活的“钩子”。
注意点:
useState 为函数组件提供状态(state)
useState 函数useState 函数,并传入状态的初始值useState 函数的返回值中,拿到状态和修改状态的方法- // 从 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+1button>
- div>
- )
- }
最新的状态值1.useState 函数可以执行多次,每次执行互相独立,每调用一次为函数组件提供一个状态;
- function List(){
- // 以字符串为初始值
- const [name, setName] = useState('zs')
- // 以数组为初始值
- const [list,setList] = useState([])
- }
2. const [状态, 更新状态的方法] = useState(初始值),注:这里的“初始值”可以是一个函数(只要函数 return 一个值就行),所以,如果初始值是需要通过一定的逻辑(比如计算)才能得到,可以写一个方法,让该方法 return 初始值即可;
3.useState 注意事项
useEffect 可以让你在函数组件中执行副作用操作
什么是副作用
副作用是相对于主作用来说的,一个函数除了主作用,其他的作用就是副作用。对于 React 组件来说,主作用就是根据数据(state/props)渲染 UI,除此之外都是副作用(比如,手动修改 DOM)
常见的副作用
useEffect 函数useEffect 函数,并传入回调函数- 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)
- }
- },[])
用于在函数组件中获取真实的dom元素对象或者是组件对象
useRef 函数useRef 函数并传入null,返回值为一个对象 内部有一个 current 属性存放拿到的dom对象(组件实例)代码实现
- 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}>Apph1>
- div>
- )
- }
-
- export default App
createContext 创建 Context 对象Provider 提供数据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+1button>p>
- div>
- Context.Provider>
- )
- }
-
- export default App
更多 hooks 详细知识-官网直达。