React-hooks

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

Hooks 的本质:一套能够使函数组件更强大,更灵活的“钩子”。

注意点:

  1. 有了 hooks 之后,为了兼容老版本,class 类组件并没有被移除,俩者都可以使用;
  2. 有了 hooks 之后,不能再把函数组件称为无状态组件了,因为 hooks 为函数组件提供了状态;
  3. hooks 只能在函数组件中使用。

useState

useState 为函数组件提供状态(state)

使用步骤

  1. 导入 useState 函数
  2. 调用 useState 函数,并传入状态的初始值
  3. 从 useState 函数的返回值中,拿到状态和修改状态的方法
  4. 在JSX中展示状态
  5. 调用修改状态的方法更新状态

代码实现

// 从 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. addCount 是一个函数,参数表示最新的状态值
  2. 调用该函数后,将使用新值替换旧值
  3. 修改状态后,由于状态发生变化,会引起视图变化

使用规则

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)

常见的副作用

  1. 数据请求 ajax 发送
  2. 手动修改 dom
  3. localstorage 操作

使用步骤

  1. 导入 useEffect 函数
  2. 调用 useEffect 函数,并传入回调函数
  3. 在回调函数中编写副作用处理(dom操作)
  4. 修改数据状态
  5. 检测副作用是否生效

代码实现

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. 不添加依赖项

组件首次渲染执行一次,以及不管是哪个状态更改引起组件更新时都会重新执行

  1. 组件初始渲染
  2. 组件更新 (不管是哪个状态引起的更新)
// 默认无依赖项的写法:
  useEffect(() => {
    document.title = count
  })  // <--注意这里

2. 添加空数组

组件只在首次渲染时执行一次

// 空数组依赖项的写法:函数体中不能使用状态
  useEffect(() => {
    document.title = 1
  }, [])   // <--注意这里

3. 添加特定依赖项

副作用函数在首次渲染时执行,在依赖项发生变化时重新执行(多个依赖项时为“或”关系)

// 依赖特定项的写法:
  useEffect(() => {
    document.title = count
  }, [count])   // <--注意这里,如果数组中有多个值,则任一值发生变化均会触发此函数执行

注意事项

useEffect 回调函数中用到的数据(比如,count)就是依赖数据,就应该出现在依赖项数组中如果不添加依赖项就会有 bug 出现

清理副作用

如果想要清理副作用 可以在副作用函数中的末尾 return 一个新的函数,在新的函数中编写清理副作用的逻辑

注意执行时机为:

  1. 组件卸载时自动执行
  2. 组件更新时,下一个useEffect副作用函数执行之前自动执行
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

用于在函数组件中获取真实的dom元素对象或者是组件对象

使用步骤

  1. 导入 useRef 函数
  2. 执行 useRef 函数并传入null,返回值为一个对象 内部有一个 current 属性存放拿到的dom对象(组件实例)
  3. 通过 ref 绑定 要获取的元素或者组件

代码实现

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

实现步骤

  1. 使用 createContext 创建 Context 对象
  2. 在顶层组件通过 Provider 提供数据
  3. 在底层组件通过 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 详细知识-官网直达

相关文章

学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习...
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面...
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生...
Can’t connect to local MySQL server through socket \'/v...
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 ...
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服...