• React-Hooks进阶:useContext、useState回调、useEffect发送网络请求和useRef


    在这里插入图片描述

    欢迎来到我的博客
    📔博主是一名大学在读本科生,主要学习方向是前端。
    🍭目前已经更新了【Vue】、【React–从基础到实战】、【TypeScript】等等系列专栏
    🛠目前正在学习的是🔥 R e a c t 框架 React框架 React框架🔥,中间穿插了一些基础知识的回顾
    🌈博客主页👉codeMak1r.小新的博客

    本文被专栏【React–从基础到实战】收录

    🕹坚持创作✏️,一起学习📖,码出未来👨🏻‍💻!
    在这里插入图片描述

    Hooks进阶

    1.useState - 回调函数的参数

    阶段目标:能够理解useState回调函数作为参数的使用场景

    使用场景

    参数只会在组件初次渲染中起作用,后续渲染时会被忽略。如果初始 state 需要通过计算才能获得,则可以传入一个函数,在函数中计算并返回初始的state,此函数只在初始渲染时被调用

    语法

    const [ name, setName ] = useState( () => {
    	// 在这里编写计算逻辑  
    	return '计算之后的初始值'
    })
    
    • 1
    • 2
    • 3
    • 4

    语法规则

    1. 回调函数 return 出去的值将作为 name 的初始值
    2. 回调函数中的逻辑只会在组件初始化的时候执行一次

    语法选择

    1. 如果就是初始化一个普通的数据,直接使用useState(defaultValue)即可
    2. 如果要初始化的数据无法直接得到,需要通过计算得到,使用useState( () => {} )

    来个需求

    页面中存在两个按钮,一个初始值为10,另一个初始值为20;另外两个按钮点击后都会有自增+1的效果。

    在这里插入图片描述

    // Counter组件
    import { useState } from 'react'
    
    export default function Counter(props) {
      const [count, setCount] = useState(() => {
        // 回调形式的useState,返回值为初始值
        return props.count
      })
      return (
        <button style={{
          backgroundColor: 'skyblue', width: '100px', height: '60px', margin: '20px'
        }} onClick={() => setCount(count + 1)}>{count}</button>
      )
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    // App组件
    import React, { Fragment } from 'react'
    import Counter from './components/11_hooks_Counter'
    
    export default function App() {
      return (
        <div>
          <Counter count={10} />
          &nbsp;&nbsp;
          <Counter count={20} />
        </div>
      )
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2.useEffect - 清理副作用

    阶段目标:能够掌握清理useEffect的方法

    使用场景

    在组件被销毁时,如果有些副作用操作需要被清理,就可以使用此语法,比如常见的定时器

    语法及规则

    useEffect(() => {
    	console.log("副作用函数执行了!")
    	// 副作用函数的执行时机为:在下一次副作用函数执行之前执行
    	return () => {
    		console.log("清理副作用的函数执行了!")
    		// 在这里写清理副作用的代码
    	}
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    定时器小案例

    添加副作用函数前:组件虽然已经不显示了,但是定时器依旧在运行

    import { useEffect,useState } from 'react'
    function Foo() {
    	useEffect( () => {
    		let timer = setInterval( () => {
    			console.log('副作用函数执行了')
    		}, 1000)
    		return () => {
    		clearInterval(timer)
    	}
    	}, [])
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    添加清理副作用函数后:一旦组件被销毁,定时器也被清理

    3.useEffect - 发送网络请求

    阶段目标:能够掌握使用useEffect hook 发送网络请求

    使用场景

    如何在useEffect中发送网络请求,并且封装同步 async/await 操作

    语法要求

    不可以直接在useEffect的回调函数外层直接包裹 await,因为异步会导致清理函数无法立即返回

    useEffect(async () => {
    	const res = await axios.get('http://geek.itheima.net/v1_0/channels')
    	console.log(res)
    },[])
    
    • 1
    • 2
    • 3
    • 4

    正确写法

    在内部单独定义一个函数,然后把这个函数包装成同步

    useEffect(() => {
      async function fetchData() {
        const res = await axios.get('http://geek.itheima.net/v1_0/channels')
        console.log(res)
      }
      fetchData()
    }, [])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4.useRef

    阶段目标:能够掌握使用useRef获取真实dom或组件实例的方法

    使用场景

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

    使用步骤

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

    获取dom

    import { useEffect, useRef } from 'react'
    function App() {  
        const h1Ref = useRef(null)  
        useEffect(() => {    
            console.log(h1Ref)  
        },[])  
        return (    
            <div>      
                <h1 ref={ h1Ref }>this is h1</h1>    
            </div>  
        )
    }
    export default App
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    获取组件实例

    函数组件由于没有实例,不能使用ref获取,如果想获取组件实例,必须是类组件

    class Foo extends Component {  
        sayHi = () => {    
            console.log('say hi')  
        }  
        render(){    
            return <div>Foo</div>  
        }
    }
        
    export default Foo
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    import { useEffect, useRef } from 'react'
    import Foo from './Foo'
    function App() {  
        const h1Foo = useRef(null)  
        useEffect(() => {    
            console.log(h1Foo)  
        }, [])  
        return (    
            <div> <Foo ref={ h1Foo } /></div>  
        )
    }
    export default App
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    5.useContext

    阶段目标:能够掌握hooks下的context的使用方式

    在这里插入图片描述

    实现步骤

    1. 使用createContext创建context对象
    2. 在顶层组件通过Provider提供数据
    3. 在底层组件通过useContext函数获取数据

    代码实现

    import { createContext, useState, useContext } from 'react'
    
    const Context = createContext()
    export default function Demo() {
      const [count, setCount] = useState(0)
      return (
        <div>
          <Context.Provider value={count}>
            <ComA />
          </Context.Provider>
        </div>
      )
    }
    
    function ComA() {
      return (
        <div>
          <ComB />
        </div>
      )
    }
    
    function ComB() {
      const count = useContext(Context)
      return (
        <div>
          <h2>我是ComB组件,我爷爷传给我的context值为:{count}</h2>
        </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

    如果有后代组件不在同一个文件中,只需要把创建的Context容器对象暴露出去即可。

    export const Context = createContext()
    
    • 1

    在其他组件的文件中使用:

    import React, { useContext } from 'react'
    import { Context } from './index'
    export default function ComC() {
      const count = useContext(Context)
      return (
        <div>
          {count}
        </div>
      )
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 相关阅读:
    Mybatis入门&Mapper开发&注解开发
    SpringCloud之Feign
    腾讯的技术牛人们,是如何完成全面上云这件事儿的?
    【MTK】 配置GPIO控制前置闪光灯
    前端开发语言有哪些
    C++:websocketpp使用
    Sublime Text 下载和安装教程
    C++入门(1)
    线程间实现通信的几种方式
    滴滴开源的APM方案Dokit接入
  • 原文地址:https://blog.csdn.net/Svik_zy/article/details/126203164