• 【React】 第十三部分 Hooks


    【React】 第十三部分 Hooks



    13. Hooks

    13.1 什么是Hooks?

    Hook是React 16.8.0版本增加的新特性/新语法

    可以让你在函数组件中使用 state ,ref 以及其他的 React 特性


    13.2 State Hook

    State Hook 作用 :让函数组件也可以有state状态, 并进行状态数据的读写操作

    在这里说几个细节上的问题:

    1. 该函数组件执行次数为 n+1 次, 1 是初始化那一次

    2. 函数重新执行按理说初始化的值会一直被覆盖,导致数据不能发生变化

      问题 :为什么数据是可以发生变化的?

      原因:react底层做了处理,在初始化的时候将初始化的值存了起来,下次
      执行的时候使用的是存起来的值

    3. StateHook中修改状态的方法不会去合并对象而是去替换对象,这点和类组件中的setState()不同

    import React, { Component } from 'react'
    
    export default function Test (){
        /*
            调用React.useState(initValue) ,传入的是初始化的值
            该方法返回的是一个数组
                - 数组中第一个参数为:初始化的值/当前状态的值
                - 数组中第二个参数为:操作该状态的方法
         */
        const [count,setCount] = React.useState(0)
        const [person,setPerson] = React.useState([
            {
                name:'Jack',
                age:18,
                id:'001'
            }
        ])
        const [obj,setObj] = React.useState({name:'Jane',age:52})
    
        const add = () =>{
            // 第一种写法,参数为非函数值
            // 直接指定新的状态值, 内部用其覆盖原来的状态值
            setCount(count+1)
        }
    
        const subtract = () =>{
            // 第二种写法,参数为函数
            // 接收原本的状态值, 返回新的状态值, 内部用其覆盖原来的状态值
            setCount(count=>count-1)
        }
    
        const addPerson = () =>{
            setPerson((person)=>{
                let obj = {id:'002',name:'Mark',age:12}
                return [obj,...person]
            })
        }
    
        /*
            在这里需要注意:它和类组件的中的setState不同
            不会进行合并对象而是去替换对象 
         */
        const changeName = () =>{
            setObj((obj)=>{
                return Object.create(Object.assign(obj,{name:'Lili'}))
            })
        }
    
        return (
            <div>
                <h2>当前求和为:{count}</h2>
                <h2 onClick={changeName}>{obj.name} --- {obj.age}</h2>
                <button onClick={add}>点我+1</button>
                <button onClick={subtract}>点我-1</button>
                <button onClick={addPerson}>添加人员</button>
                {
                    person.map((item)=>{
                        return <li key={item.id}>{item.name} --- {item.age}</li>
                    })
                }
            </div>
        )
    }
    
    
    • 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
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    13.3 Effect Hook

    Effect Hook 作用: 可以在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)

    React中的副作用操作:

    1. 发ajax请求数据获取
    2. 设置订阅 / 启动定时器
    3. 手动更改真实DOM
    4. 清除定时器
    
    • 1
    • 2
    • 3
    • 4

    useEffect Hook 可以看做如下三个生命周期组合

    componentDidMount()

    componentDidUpdate()

    componentWillUnmount()

    第一种写法: 
    React.useEffect(()=>{
          // 相当于 componentDidUpdate()
       		// 监视所有的数据一旦数据发生变化就调用该函数
       		console.log('@');
     })
    
    
    第二种写法:
    React.useEffect(()=>{
          // 相当于 componentDidUpdate()
       		// 第二个函数可以传入一个数组,数组内可以指定监视某个属性
      		// 监视的属性一旦发生变化就调用该函数
       		console.log('@');
     },[count])
    
    
    第三种写法:
    React.useEffect(()=>{
       // 如果只写一个数组那么就表示谁也不监视
      // 只在初始化的时候执行一次,相当于componentDidMount()
       console.log('@');
    },[])
    
    
    第四种写法:
      React.useEffect(()=>{
           return ()=>{
             // 该函数中只有在组件将要被卸载的时候才会执行
             // 相当于componentWillUnmount()
            	console.log('@');
           }
    },[])
    
    • 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

    13.4 Ref hook

    Ref Hook 作用 :可以在函数组件中存储/查找组件内的标签或任意其它数据

    语法:const refContainer = React.useRef()

    用法和React.createRef()一样

    import React, { Component } from 'react'
    
    export default function Demo(){
        // 创建一个存放ref的容器
        const inpRef = React.useRef()
        
        const tip = () =>{
            alert(inpRef.current.value)
        }
    
        return (
            <div>
                <input type="text" ref={inpRef} />
                <button onClick={tip}>alert</button>
            </div>
        )
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    13.5 useCallback(记忆函数)

    作用:防止组件重新渲染时,导致函数重新进行创建,对函数起到缓存作用

    根据下面这个案例,不管是修改数值还是修改名字,只要一修改那么整个函数式组件就会重新被渲染, 函数就会被重新创建声明,useCallBack( )就是为了解决这个问题而诞生,可以提高性能优化

    import React, { useState, useCallback } from 'react'
    
    export default function CallBack() {
        const [count, setCount] = useState(0)
        const [name,setName] = useState('Jack')
        /*
            useCallback()可以传入两个参数
                - 第一个参数就是我们所写的逻辑
                - 第二个参数就是逻辑中所依赖的属性
            函数在第一次创建的时候就被缓存,只有所依赖的属性发生
            变化才会重新创建声明函数
         */
        const handleAdd = useCallback(
            () => {
                setCount(count + 1 )
            },
            [count]
        )
    
        const modifyName = useCallback(
            () =>{
                setName('LiHua')
            },[]
        )
    
        return (
            <div>
                <h2>当前的值为:{count}</h2>
                <button onClick={() => { handleAdd() }}>add</button>
                <h2>{name}</h2>
                <button onClick={modifyName}>点击修改名字</button>
            </div>
        )
    }
    
    
    • 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
    • 34
    • 35

    13.6 useMemo (记忆组件)

    useCallback的功能完全可以由useMemo所替代

    那么它们之间的区别在于哪里呢?

    1. 写法

      useCallback(fn,[attr])   
      useMemo(()=> fn, [attr])
      
      • 1
      • 2
    2. 用法

      useCallback不会执行第一个参数中的函数,而是直接将该函数返回,而useMemo会执行第一个参数中的函数并且将函数执行的结果返回给你,学过Vue的小伙伴应该就知道这个相当于Vue中计算属性

    3. 使用场景

      useCallback常用于记忆事件函数,而useMemo更适合通过一个函数计算得到一个确定的值

      import axios from 'axios'
      import React,{useState,useMemo,useEffect,useCallback} from 'react'
      
      export default function UseMemo() {
        const [inpVal,setInpVal] = useState('')
        const [list,setList] = useState([])
      
        useEffect(()=>{
          axios({
              url:'https://m.maizuo.com/gateway?cityId=310100&ticketFlag=1&k=5006381',
              headers:{
                  'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.2.1","e":"1660449552376256314998785","bc":"310100"}',
                  'X-Host': 'mall.film-ticket.cinema.list'
              }
          }).then((value)=>{
              setList(value.data.data.cinemas)
          }).catch((error)=>{
              console.log(error);
          })
        },[])
      
        // 处理搜索
        const handleSearch = useCallback(
          (e) =>{
              setInpVal(e.target.value)
            },[]
        )
      
        // 筛选符合条件的内容
        const filterData = useMemo(()=>{
          return list.filter((item)=>{
              return item.name.toUpperCase().includes(inpVal.toUpperCase()) || item.address.toUpperCase().includes(inpVal.toUpperCase())
          })
        },[list,inpVal])
      
        return (
          <div>
              <input type="text"  onChange={handleSearch}/>
              <ul>
                  {
                      filterData.map((item)=>{
                          return (
                              <li key={item.cinemaId}>
                                  <h3>{item.name}</h3>
                                  <h5>{item.address}</h5>
                              </li>
                          )
                      })
                  }
              </ul>
          </div>
        )
      }
      
      
      • 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
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54

    13.7 useContext

    作用:适用于祖先和后代间通信

    import React ,{createContext,useContext}from 'react'
    
    // 第一步: 创建context对象
    const GlobalContext = createContext()
    export default function UseContextTest() {
      return (
            // 第二步: GlobalContext.Provider包裹祖先,让他成为供应商
            // value属性:传入数据
            <GlobalContext.Provider value={{
                info:'这是祖先传递的消息',
                message:()=>{
                    console.log('这是祖先传递的方法');
                }
            }}>
                <div style={{padding:'10px',background:'green'}}>
                    <h2>我是祖先</h2>
                    <Father></Father>
                </div>
            </GlobalContext.Provider>
      )
    }
    
    
    
    function Father() {
      return (
        <div style={{padding:'10px',background:'pink'}}>
            <h2>我是儿子</h2>
            <Son></Son>
        </div>
      )
    }
    
    function Son() {
    
      // 第三步:通过useContext(context对象)
      const value = useContext(GlobalContext)
      return (
        <div style={{padding:'10px',background:'red'}}>
            <h2>我是孙子</h2>
            <h4>{value.info}</h4>
            <h4>{value.message()}</h4>
        </div>
      )
    }
    
    
    • 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
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    13.8 useReducer

    作用:用于状态管理,和redux作用一样,也是根据redux所创造出来的hook,那么它需要配合useContext一起使用

    import React,{useReducer} from 'react'
    
    export default function UseReducer() {
      const initState = {count:0}
      /*
            reducer处理函数可以接收到两个参数
                - 第一个参数:之前状态的值
                - 第二个参数:所派发的action
                    - action是一个对象里面存放type和data
       */
      const reducer = (previousState=initState,action)=>{
        const {type,data} = action
        switch (type) {
            case 'plus':
                return {count:previousState.count + data}
            case 'subtract':
                return {count:previousState.count - data}
            default:
                return previousState
        }
      }
       /*
            useReducer可以接收到两个参数
                - 第一个参数:总状态
                - 第二个参数:dispatch用来派发action
            useReducer需要传入到两个参数
                - reducer:处理函数
                - initState:初始化状态
    
       */
      const [state,dispatch] = useReducer(reducer,initState)
      return (
        <div>
            <h2>当前的值为:{state.count}</h2>
            <button onClick={()=>{
                dispatch({type:'plus',data:1})
            }}> +1 </button>
            <button onClick={()=>{
                dispatch({type:'subtract',data:1})
            }}> -1 </button>
        </div>
      )
    }
    
    
    • 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
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    13.9 自定义hook

    自定义 Hook 是一个函数,其名称以 “use” 开头,函数内部可以调用其他的 Hook。

    其实本质上就是提取公共部分的逻辑,对其进行函数封装

    import {useState,useEffect} from 'react'
    import axios from 'axios'
    export default function useGetData() {
        const [getData,setData] = useState([]) 
        useEffect(()=>{
            axios({
                url: 'https://m.maizuo.com/gateway?cityId=350600&ticketFlag=1&k=8644263',
                headers: {
                    'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.2.1","e":"1660449552376256314998785","bc":"350600"}',
                    'X-Host': 'mall.film-ticket.cinema.list'
                }
            }).then((value) => {
                setData(value.data.data.cinemas)
            }).catch((error) => {
                console.log(error)
            })
        },[])
    
        return getData
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    总结

    以上就是今天要讲的内容,希望对大家有所帮助!!!

  • 相关阅读:
    多模态论文阅读之BLIP
    k8s实战系列:3-存储的花样玩法(下)
    clickhouse技术总结待续
    软件测试/测试开发丨Python模块与包 学习笔记
    Triple-shapelet Networks for Time SeriesClassification(ICDM2020)
    堆排序及哈夫曼编码实现数据压缩
    正则表达式的学习笔记
    基于 Spring Boot 博客系统开发(一)
    怎么注册微信小程序、微信小程序注册流程说明
    Kettle——大数据ETL工具
  • 原文地址:https://blog.csdn.net/Trees__/article/details/126540123