我是靠谱客的博主 自信煎饼,最近开发中收集的这篇文章主要介绍Hooks进阶--useEffect - 发送网络请求1.useState - 回调函数的参数2.useEffect - 清理副作用3.定时器小案例4.useEffect - 发送网络请求5.useRef5.useContext1.实现步骤,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1.useState - 回调函数的参数

使用场景

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

语法

const [name, setName] = useState(()=>{    // 编写计算逻辑    return '计算之后的初始值'})

语法规则

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

语法选择

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

eg。

import { useState } from 'react'

// 计算的含义
function getDefaultValue(){
    for(let i =0 ;i<1000;i++){
    }
    return '10'
}

function Counter(props) {
  const [count, setCount] = useState(() => {
    // 这里目的:为了体现初始值经过一定的计算
    // 这个计算比较广义的概念
    // 只要无法直接确定,需要通过一定的操作才能获取,
    // 就可以理解为计算
    // 循环遍历一万条数据,才能确定这里的初始值是什么
    return props.count
    ------------------------
    return getDefaultValue()
  })
  return (
    <div>
      <button onClick={() => setCount(count + 1)}>{count}</button>
    </div>
  )
}

function App() {
  return (
    <>
      <Counter count={10} />
      <Counter count={20} />
    </>
  )
}

export default App

2.useEffect - 清理副作用

有一些副作用是需要清除的,可以防止引起内存泄露。

1.使用场景

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

2.语法及规则

useEffect(() => {   
    console.log('副作用函数执行了')    
    // 副作用函数的执行时机为: 在下一次副作用函数执行之前执行   
    return () => {      
        console.log('清理副作用的函数执行了')      
        // 在这里写清理副作用的代码    
    }
})

3.代码复现:

import { useEffect, useState } from 'react'

function Test () {
//清除副作用effect
    useEffect(() => {
        let timer = setInterval(() => {
            console.log('定时器执行了')
        }, 1000)
        return () => {//执行时机:React将会在执行清除操作时调用它--componentWillMount
            //清理的动作
            clearInterval(timer)
        }
    }, [])
    return (
        <div>this is test</div>
    )
}

function App () {
    const [flag, setFlag] = useState(true)
    return (
        <>
            {flag ? <Test /> : null}
            <button onClick={() => setFlag(!flag)}>switch</button>
        </>
)}

将setFlag作为函数书写的案例:

import { useEffect, useState } from 'react'
function A () {
  useEffect(() => {
    let timer = setInterval(() => {
      console.log(111)
    }, 1000)
    return () => {
      clearInterval(timer)
    }
  })

  return (
    <div>
      A组件
    </div>

  )
}
function App () {
  const [isShow, setIsShow] = useState(true)
  function changeA () {
    setIsShow(false)
  }
  return (
    <div>
      {isShow ? <A /> : null}
      <button onClick={changeA}>销毁A组件</button>
    </div>
)}

3.定时器小案例

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

import { useEffect, useState } from 'react'
function Foo() {  
    useEffect(() => {    
        setInterval(() => {     
            console.log('副作用函数执行了')    
        }, 1000)  
    }) 
    return <div>Foo</div>  
}


function App() {  
    const [flag, setFlag] = useState(true)  
    return (    
        <>      
          <button onClick={() => setFlag(false)}>click</button>      
         {flag ? <Foo/> : null}    
        </>  
    )
}

export default App

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

import { useEffect, useState } from 'react'

function Foo() {  
    useEffect(() => {   
        const timerId = setInterval(() => {      
            console.log('副作用函数执行了')    
        }, 1000)   
        // 添加清理副租用函数    
        return () => {      
            clearInterval(timerId)    
        }  
    })  
    return <div>Foo</div>
}
function App() {  
    const [flag, setFlag] = useState(true)  
    return (   
        <>      
          <button onClick={() => setFlag(false)}>click</button>      
         {flag ? <Foo/> : null}    
        </>    
    )
}

export default App

4.useEffect - 发送网络请求

类组件如何发送网络请求?

发送网络请求的生命周期钩子函数:componentDidMount

执行时机?

在初始化的时候dom渲染完毕时,只执行一次

useEffect

  • 不加依赖项 - 初始化 + 重新渲染
  • 加[ ] - 初始化执行一次
  • 加特定的依赖项[count,name] - 首次执行 +任意一个变化执行

1.使用场景

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

2.语法要求

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

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

3.正确写法

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

useEffect(()=>{   
  async function fetchData(){      
      // await fetch也可以,百度搜索
   const res = await axios.get('http://geek.itheima.net/v1_0/channels')
   console.log(res)   
    } 
},[])

复制一张图片的地址,可以将图片请求出来:

function A () {
  const [imgs, setImgs] = useState('')
  useEffect(() => {
    const res = fetch('https://fastly.jsdelivr.net/npm/@vant/assets/logo.png')
    console.log(res)
    res.then((value) => {
      console.log(value)//返回的是一个结果
      setImgs(value.url)
    })
  },[])

  return (
    <div>
      A组件
      <img src={imgs} alt="" />
    </div>
)}

 

useEffect发送网络请求,只请求一次的话,依赖项就设置为空数组 。

5.useRef

useRef获取真实dom或组件实例。返回一个可变的ref对象,其中.current属性被初始化为传入的参数,

1.使用场景

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

2.使用步骤

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

3.获取dom

import { useEffect, useRef } from 'react'

class Test extends React.Component {
    render () {
        return (
            <div>类组件</div>
        )
    }
}

function App() {  
  const testRef = useRef(null)
    const h1Ref = useRef(null)  
    //useEffect回调:在dom渲染之后
    // vue里的watch效果比较像,但执行时机时不同的
    useEffect(() => {  
       console.log(testRef.current)
       console.log(h1Ref.current) 
        console.log(h1Ref)  
    },[])  
    return (    
        <div>      
            <Test ref={testRef} />
            <h1 ref={ h1Ref }>this is h1</h1>    
        </div>  
    )
}
export default App

在Test中加入函数,state等

state={
        name:'zz'
    }
    getName=()=>{
        return 'child test'
    }

4.获取组件实例

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

Foo.js

class Foo extends React.Component {  
    sayHi = () => {    
        console.log('say hi')  
    }  
    render(){    
        return <div>Foo</div>  
    }
}
    
export default Foo

App.js

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

5.useContext

在函数组件中跨组件通信 

  • 接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。
  • 当前的 context 值由上层组件中距离当前组件最近的 <MyContext.Provider> 的 value prop 决定。 

1.实现步骤

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

2.代码实现

import { createContext, useContext } from 'react'
// 1.创建Context对象
const Context = createContext()

function Foo() {  
    return <div>Foo <Bar/></div>
}

function Bar() {  
    // 3.底层组件通过useContext函数获取数据  
    // usseContext(createContext返回的对象)
//通过调用useContext,将Context对象传过去,得到当前的传过去的Context的值
    const name = useContext(Context)  
    return <div>Bar {name}</div>
}

function App() {  
    return (    
        // 2.顶层组件通过Provider 提供数据    
        <Context.Provider value={'this is name'}>     
            <div><Foo/></div>    
        </Context.Provider>  
    )
}

export default App

3.单独写

1.把createContext分装出去,创建context.js ---要记得都保存

import { createContext } from "react"

const Context = createContext()

export default Context

2.App.js引用context.js

import Context from './context'

完整代码:

import React, { useContext, useState } from 'react'

import Context from './context'

function ComA () {
  const count = useContext(Context)
  return (
    <div>
      ComA
      <br />
      app传过来的数据为:{count}
      <ComC />
    </div>
  )
}

function ComC () {
  const count = useContext(Context)
  return (
    <div>
      ComC
      <br />
      app传过来的数据为:{count}
    </div>
  )
}

function App () {
  const [count, setCount] = useState(20)
  return (

    <Context.Provider value={count}>
      <div>
        <ComA />
        <button onClick={() => { setCount(count + 1) }}>+</button>
      </div>
    </Context.Provider>
  )
}

export default App

4.也可以在index.js中使用createContext

1.index.js中引入context.js

import Context from './context'

2.除去App.js中的以下内容

<Context.Provider value={count}>
const [count, setCount] = useState(20)

3.index.js中添加

<React.StrictMode>
// 这个value只能传递一次,是什么就是什么
    <Context.Provider value={100}>
    <App />
    </Context.Provider>
</React.StrictMode>,

context如果要传递的数据,只需要在整个应用初始化的时候传递一次就可以,可以选择在当前文件里做数据提供,index.js->静态的

context如果需要传递数据并且将来还需要再对数据做修改,底层组件也需要变,所以可以写到App.js中->动态的

阶段小练习-todoMvc-hook版

案例仓库地址:

react课程全系列/react-tomvc-hook

项目演示步骤:

  1. 克隆项目到本地
    git clone  https://gitee.com/react-course-series/react-tomvc-hook.git
    
  2. 安装必要依赖
    yarn
    
  3. 开启mock接口服务,保持窗口不关闭 !!!!!
    # 启动mock服务
    yarn mock-serve
    
  4. 另起一个bash窗口开启前端服务
    yarn start
    
  5. 浏览器输入 localhost:3000演示效果

项目开发步骤:

  1. 切换到todo-test分支

    git checkout todo-test
    
  2. 打开 app.js

    已有基础样板代码,在这个基础上编写业务逻辑即可

  3. 接口文档

    接口作用接口地址接口方法接口参数
    获取列表http://localhost:3001/dataGET
    删除http://localhost:3001/data/:idDELETEid
    搜索http://localhost:3001/data/?q=keywordGETname(以name字段搜索)

实现功能

功能核心思路
表格数据渲染elementPlus el-table组件使用
删除功能获取当前id 调用接口
搜索功能用的依旧是列表接口,多传一个name参数
清除搜索功能清空搜索参数 重新获取列表

最后

以上就是自信煎饼为你收集整理的Hooks进阶--useEffect - 发送网络请求1.useState - 回调函数的参数2.useEffect - 清理副作用3.定时器小案例4.useEffect - 发送网络请求5.useRef5.useContext1.实现步骤的全部内容,希望文章能够帮你解决Hooks进阶--useEffect - 发送网络请求1.useState - 回调函数的参数2.useEffect - 清理副作用3.定时器小案例4.useEffect - 发送网络请求5.useRef5.useContext1.实现步骤所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部