react中如何理解usestate、useEffect副作用、useRef标识和useContext

本文主要是介绍react中如何理解usestate、useEffect副作用、useRef标识和useContext,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.usestate

1.1一般使用

注意:useState 的初始值(参数)只会在组件第一次渲染时生效。也就是说,以后的每次渲染,useState 获取到都是最新的状态值,React 组件会记住每次最新的状态值。

其实与vue中的ref和reactive一样,通过useState获取到的数据可以实现组件视图实时交互,而普通定义的数据仅仅在业务中使用。

使用规则:
1.每个useState 函数可以执行多次,每次执行互相独立,每调用一次为函数组件提供一个状态 。
2. 只能出现在函数组件或者其他hook函数中 。
3. 不能嵌套在if/for/其它函数中(react按照hooks的调用顺序识别每一个hook)。

import { useState } from 'react'function App() {const [count, setCount] = useState(0)// 在这里可以进行打印测试console.log(count)return (<button onClick={() => { setCount(count + 1) }}>{count}</button>)
}
export default App

初始值为泛型时:

interface LayerCheckbox {name: string;checked?: boolean;value?: string[];disabled?: boolean;children?: LayerCheckbox[];indeterminate?: boolean;key: string; // gis layer keyrelevance?: string;
}
const [checkboxArr, setCheckboxArr] = useState<LayerCheckbox[]>([name: '高清影像图',checked: true,key: LayerEnum.TILES_MAP,},{name: '农场地块信息',checked: true,key: LayerEnum.FIELD_AREA,},{name: '灌溉设备图层',checked: true,key: LayerEnum.DRAIN_IRRIGATE,},{name: '农情设备图层',checked: true,key: LayerEnum.CONDITION_DEVICE,},]);

1.2 useState回调函数作为参数

场景: useState初始值在回调函数里通过计算处理等函数操作得到

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

2.useEffect副作用

2.1 useEffect副作用及其使用

副作用是相对于主作用来说的,一个函数除了主作用,其他的作用就是副作用。对于 React 组件来说,主作用就是根据数据(state/props)渲染 UI,除此之外都是副作用(比如,手动修改 DOM)。
常见副作用:
1.数据请求 ajax发送
2.手动修改dom
3.localstorage操作
useEffect函数的作用就是为react函数组件提供副作用处理的!

代码如下(示例):

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

使用的三种场景:

1.不添加依赖项
组件首次渲染执行一次,以及不管是哪个状态更改引起组件更新时都会重新执行。
1)组件初始渲染
2)组件更新 (不管是哪个状态引起的更新)

useEffect(()=>{console.log('副作用执行了')
})

2.添加空数组
组件只在首次渲染时执行一次

useEffect(()=>{console.log('副作用执行了')
},[])
})

3.添加特定依赖项
副作用函数在首次渲染时执行,在依赖项(count)发生变化时重新执行。

function App() {  const [count, setCount] = useState(0)  const [name, setName] = useState('zs') useEffect(() => {    console.log('副作用执行了')  }, [count])  return (    <>      <button onClick={() => { setCount(count + 1) }}>{count}</button>      <button onClick={() => { setName('cp') }}>{name}</button>    </>  )
}

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

2.2 useEffect清理副作用

如果想要清理副作用 可以在副作用函数中的末尾return一个新的函数,在新的函数中编写清理副作用的逻辑。
注意执行时机为:
1.组件卸载时自动执行
2.组件更新时(count一变时),下一个useEffect副作用函数执行之前自动执行

import { useEffect, useState } from "react"
const App = () => {const [count, setCount] = useState(0)
//页面初始化就执行一次,执行后count+1,依赖count变化,又来执行一次,此刻组件更新了,因此会清除副作用useEffect(() => {const timerId = setInterval(() => {setCount(count + 1)}, 1000)return () => {// 用来清理副作用的事情clearInterval(timerId)}}, [count])return (<div>{count}</div>)
}
export default App

2.3 useEffect发送网络请求

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

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

3.自定义hook函数

useState与useEffect都属于hook中的函数,那么也可以自己定义hook函数,利用useState和useEffect来实现自定义的hook函数,以便在其他地方调用。如:自定义一个hook函数,实现获取滚动距离Y。在其他地方调用此函数,就可以拿到这个y进行渲染或其他处理操作。

//自定义hook
import { useState } from "react"export function useWindowScroll () {
const [y, setY] = useState(0)
window.addEventListener('scroll', () => {const h = document.documentElement.scrollTopsetY(h)
})
return [y]//调用区
import {useWindowScroll } from './hoooks/useWindowScroll '
const [y] =  useWindowScroll () 
return(<div> {y} </div>
)

自定义一个hook函数,监听依赖项(messge),实现一个功能(存储带本地):

//hook函数
import { useEffect, useState } from 'react'
//message可以通过自定义传入默认初始值
export function useLocalStorage (key, defaultValue) {
const [message, setMessage] = useState(defaultValue)
// 每次只要message变化 就会自动同步到本地ls
useEffect(() => {window.localStorage.setItem(key, message)
}, [message, key])
return [message, setMessage]
}//调用区
import {useLocalStorage  } from './hoooks/useLocalStorage '
const [messge,setMessage] = useLocalStorage ('hook-key','阿飞')
//初始值是 阿飞,5秒钟后变成 cp
setTimeout(()=>{setMessage('cp')
},5000)

4.useRef的使用

useRef能在函数组件中获取真实的dom元素对象或者是组件对象。
首先执行 useRef 函数并传入null,返回值为一个对象内部有一个current属性存放拿到的dom对象(组件实例),在使用时通过ref 绑定 要获取的元素或者组件。
1)获取dom <dom名 ref={ h1Ref }>

import { useEffect, useRef } from 'react'
function App() {  const h1Ref = useRef(null)  useEffect(() => {//h1Ref.current就指h1这个dom    console.log(h1Ref)  },[])  return (    <div>      <h1 ref={ h1Ref }>this is h1</h1>    </div>  )
}
export default App

2)获取组件实例 <组件名 ref={ h1Foo }>

//类组件
class Foo extends React.Component {  sayHi = () => {    console.log('say hi')  }  render(){    return <div>Foo</div>  }
} 
export default Foo//获取组件实例
import { useEffect, useRef } from 'react'
import Foo from './Foo'
function App() {  const h1Foo = useRef(null)  useEffect(() => { //h1Foo.current就指Foo组件console.log(h1Foo)  }, [])  return (    <div> <Foo ref={ h1Foo } /></div>  )
}
export default App

5.useContext的使用

实现步骤:
1.使用createContext 创建Context对象
2.在顶层组件通过Provider 提供数据
3.在底层组件通过useContext函数获取数据
在这里插入图片描述

import { createContext, useContext } from 'react'
// 创建Context对象
const Context = createContext()function A() {  return <div>A中里面包裹C组件<C/></div>
}function C() {  // 底层组件通过useContext函数获取数据  const name = useContext(Context)  return <div>C中{name}</div>
}function App() {  return (    // 顶层组件通过Provider 提供数据    <Context.Provider value={'this is name'}>     <div><Foo/></div>    </Context.Provider>  )
}
export default App

一样地,在顶层组件中Context.Provider这个value,然后在C组件中消费接受数据,由于A组件下面包裹着C组件,当A组件中执行C组件时,可以看到里面可以拿到value数据。
实际还是在“被包裹的组件(C)”中消费接收数据。
不论中间隔着几层,谁发数据谁provider,谁收数据谁useContext

这篇关于react中如何理解usestate、useEffect副作用、useRef标识和useContext的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/365285

相关文章

vite搭建vue3项目的搭建步骤

《vite搭建vue3项目的搭建步骤》本文主要介绍了vite搭建vue3项目的搭建步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录1.确保Nodejs环境2.使用vite-cli工具3.进入项目安装依赖1.确保Nodejs环境

Nginx搭建前端本地预览环境的完整步骤教学

《Nginx搭建前端本地预览环境的完整步骤教学》这篇文章主要为大家详细介绍了Nginx搭建前端本地预览环境的完整步骤教学,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录项目目录结构核心配置文件:nginx.conf脚本化操作:nginx.shnpm 脚本集成总结:对前端的意义很多

深入理解Mysql OnlineDDL的算法

《深入理解MysqlOnlineDDL的算法》本文主要介绍了讲解MysqlOnlineDDL的算法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小... 目录一、Online DDL 是什么?二、Online DDL 的三种主要算法2.1COPY(复制法)

前端缓存策略的自解方案全解析

《前端缓存策略的自解方案全解析》缓存从来都是前端的一个痛点,很多前端搞不清楚缓存到底是何物,:本文主要介绍前端缓存的自解方案,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、为什么“清缓存”成了技术圈的梗二、先给缓存“把个脉”:浏览器到底缓存了谁?三、设计思路:把“发版”做成“自愈”四、代码

通过React实现页面的无限滚动效果

《通过React实现页面的无限滚动效果》今天我们来聊聊无限滚动这个现代Web开发中不可或缺的技术,无论你是刷微博、逛知乎还是看脚本,无限滚动都已经渗透到我们日常的浏览体验中,那么,如何优雅地实现它呢?... 目录1. 早期的解决方案2. 交叉观察者:IntersectionObserver2.1 Inter

Vue3视频播放组件 vue3-video-play使用方式

《Vue3视频播放组件vue3-video-play使用方式》vue3-video-play是Vue3的视频播放组件,基于原生video标签开发,支持MP4和HLS流,提供全局/局部引入方式,可监听... 目录一、安装二、全局引入三、局部引入四、基本使用五、事件监听六、播放 HLS 流七、更多功能总结在 v

JS纯前端实现浏览器语音播报、朗读功能的完整代码

《JS纯前端实现浏览器语音播报、朗读功能的完整代码》在现代互联网的发展中,语音技术正逐渐成为改变用户体验的重要一环,下面:本文主要介绍JS纯前端实现浏览器语音播报、朗读功能的相关资料,文中通过代码... 目录一、朗读单条文本:① 语音自选参数,按钮控制语音:② 效果图:二、朗读多条文本:① 语音有默认值:②

vue监听属性watch的用法及使用场景详解

《vue监听属性watch的用法及使用场景详解》watch是vue中常用的监听器,它主要用于侦听数据的变化,在数据发生变化的时候执行一些操作,:本文主要介绍vue监听属性watch的用法及使用场景... 目录1. 监听属性 watch2. 常规用法3. 监听对象和route变化4. 使用场景附Watch 的

前端导出Excel文件出现乱码或文件损坏问题的解决办法

《前端导出Excel文件出现乱码或文件损坏问题的解决办法》在现代网页应用程序中,前端有时需要与后端进行数据交互,包括下载文件,:本文主要介绍前端导出Excel文件出现乱码或文件损坏问题的解决办法,... 目录1. 检查后端返回的数据格式2. 前端正确处理二进制数据方案 1:直接下载(推荐)方案 2:手动构造

Vue实现路由守卫的示例代码

《Vue实现路由守卫的示例代码》Vue路由守卫是控制页面导航的钩子函数,主要用于鉴权、数据预加载等场景,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录一、概念二、类型三、实战一、概念路由守卫(Navigation Guards)本质上就是 在路