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

目录
  • 1.usestate
    • 1.1一般使用
    • 1.2 useState回调函数作为参数
  • 2.useEffect副作用
    • 2.1 useEffect副作用及其使用
    • 2.2 useEffect清理副作用
    • 2.3 useEffect发送网络请求
  • 3.自定义hook函数
  • 4.useRef的使用
  • 5.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 key
  relevance?: 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.scrollTop
  setY(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(() => {
        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(() => {
        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的文章就介绍到这了,更多相关react usestate useEffect副作用 useRef标识和useContext内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • react中使用useEffect及踩坑记录

    目录 使用useEffect及踩坑记录 useEffect 介绍 useEffect常见跳坑 hooks中useEffect()使用总结 常见使用 useEffect() 的第二个参数说明 useEffect() 第一个函数参数的返回值 useEffect() 的注意点 使用useEffect及踩坑记录 useEffect 介绍 useEffect时reactHook中最重要,最常用的hook之一. useEffect相当于react中的什么生命周期呢? 这个问题在react官网中有过介绍,在使

  • React useEffect的理解与使用

    React16.8新增的useEffec这个hook函数就是处理副作用的. 所谓的"副作用",举个通俗一点的例子,假如感冒了本来吃点药就没事了,但是吃了药发现身体过敏了,而这个"过敏"就是副作用. 放到React中,本来只是想渲染DOM展示到页面上,但除了DOM之外还有数据,而这些数据必须从外部的数据源中获取,这个"获取外部数据源"的过程就是副作用. useEffect怎么用可以参考官网给出的例子,这里主要针对使用useEffect过程中遇到的问

  • React 中的 useContext使用方法

    目录 什么是上下文呢? useContext使用的方法: 1.要先创建createContex 2.Provider 指定使用的范围 3.最后使用useContext useContext就是上下文 什么是上下文呢? 全局变量就是全局的上下文,全局都可以访问到它:上下文就是你运行一段代码,所要知道的所有变量 useContext使用的方法: 1.要先创建createContex 使用createContext创建并初始化 const C = createContext(null); 2.Prov

  • React中hook函数与useState及useEffect的使用

    目录 1. 简介 2. useState使用 3. useEffect使用 useEffect发起网络请求 1. 简介 在 React 的世界中,有容器组件和 UI 组件之分,在 React Hooks 出现之前,UI 组件我们可以使用函数组件,无状态组件来展示 UI,而对于容器组件,函数组件就显得无能为力,我们依赖于类组件来获取数据,处理数据,并向下传递参数给 UI 组件进行渲染.React在v16.8 的版本中推出了 React Hooks 新特性,Hook是一套工具函数的集合,它增强了函数

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

    目录 1.usestate 1.1一般使用 1.2 useState回调函数作为参数 2.useEffect副作用 2.1 useEffect副作用及其使用 2.2 useEffect清理副作用 2.3 useEffect发送网络请求 3.自定义hook函数 4.useRef的使用 5.useContext的使用 1.usestate 1.1一般使用 注意:useState 的初始值(参数)只会在组件第一次渲染时生效.也就是说,以后的每次渲染,useState 获取到都是最新的状态值,React

  • React中useRef的具体使用

    相信有过React使用经验的人对ref都会熟悉,它可以用来获取组件实例对象或者是DOM对象. 而useRef这个hooks函数,除了传统的用法之外,它还可以"跨渲染周期"保存数据. 首先来看一下它传统的用法: import React, { useState, useEffect, useMemo, useRef } from 'react'; export default function App(props){ const [count, setCount] = useState(

  • 关于react中useCallback的用法

    目录 基础用法 父组件 子组件 useCallback是react中比较重要的一个hook useCallback 用来返回一个函数,在父子组件传参或者通用函数封装中,起到举足轻重的作用. 基础用法 useCallback的用法与useState的用法基本一致,但最后会返回一个函数,用一个变量保存起来. 返回的函数a会根据b的变化而变化,如果b始终未发生变化,a也不会重新生成,避免函数在不必要的情况下更新. 记得子组件导出时使用memo包裹一下,其作用是对组件前后两次进行浅对比,阻止不必要的更新

  • React中的Hooks进阶理解教程

    目录 Hooks进阶 useState - 回调函数的参数 useEffect - 清理副作用 useEffect - 发送网络请求 useRef useContext Hooks进阶 useState - 回调函数的参数 使用场景 参数只会在组件的初始渲染中起作用,后续渲染时会被忽略.如果初始 state 需要通过计算才能获得,则可以传入一个函数,在函数中计算并返回初始的 state,此函数只在初始渲染时被调用 语法 const [name, setName] = useState(()=>{

  • react中的watch监视属性-useEffect介绍

    目录 react的watch监视属性-useEffect useEffect使用指南 最基本的使用 响应更新 如何处理Loading和Error 处理表单 自定义hooks 使用useReducer整合逻辑 取消数据请求 react的watch监视属性-useEffect 在vue中可以使用watch属性,去监视一个值,当这个值进行变化的时候就去执行一些操作.在react是没有这个属性的,但是它也一样可以达到相同的效果,那么接下来看看它是怎么实现的呢? 在react中实现监听效果有一个比较简单的

  • React中useEffect 与 useLayoutEffect的区别

    目录 前置知识 useEffect commitBeforeMutationEffects commitMutationEffects commitLayoutEffects 后续阶段 useLayoutEffect 结论 前置知识 我们可以将 React 的工作流程划分为几大块: render 阶段:主要生成 Fiber节点 并构建出完整的 Fiber树 commit 阶段:在上一个render 阶段中会在 rootFiber 上生成一条副作用链表,应用的DOM操作就会在本阶段执行 commi

  • 教你在react中创建自定义hooks

    一.什么是自定义hooks 逻辑复用 简单来说就是使用自定义hook可以将某些组件逻辑提取到可重用的函数中. 自定义hook是一个从use开始的调用其他hook的Javascript函数. 二.不使用自定义hook时 例1:当我们整个页面需要获取用户鼠标移动的坐标时,不使用hook的代码,我们可以这样写 const [position, setPosition] = useState({ x: 0, y: 0 }) useEffect(() => { const move = (e) => {

  • 关于 React 中 useEffect 使用问题浅谈

    目录 前言 优化前 优化后 总结 前言 最近看了一下 ant-design 中的 tree 组件源码时发现 useEffect 中根据 props 来计算当前函数组件的 state 的,感到好奇,因为这样会导致应用重新绘制一次,这样才复杂场景下会对应用有一定的性能影响.为了验证自己猜想是否正确做了一下实践.这里的 React 是官方 16.12.0的源码. 优化前 import * as React from './react-source/packages/react' import * as

随机推荐