IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> react-10(stateHook,effect Hook) -> 正文阅读

[JavaScript知识库]react-10(stateHook,effect Hook)

State Hook

1、16.8以后的新特性,现在可用

2、我们之前的组件都是以类的概念来实现的,里面可以 写函数、属性、state、视图,hook就是让我们在不写类的情况下也能实现效果,hook在类组件丽不生效。 (函数组件 )

3、没有计划移除class,hook和class并存。(可以写类组件,也可以写函数组件)

hook是什么?

????????hook是react的一个特殊的函数,可以引入react的特性,系统的调用函数,useState()后面就带了个括号。

state Hook声明:

????????在函数组件中,我们没有?this,所以我们不能分配或读取?this.state?,使用useState,我们可以直接拿到。

const [state, setState] = useState(initialState);
// [属性名,改变属性方法] = useState(属性初始值);

const [state, setState] = useState(function);
// [属性名,改变属性方法] = useState(需要通过计算得到初始值的方法);

函数组件对比类组件:

函数组件对比类组件
函数组件(hook)类组件
不需要赋值this.state需要赋值this.state
更新数据直接更新需要调用this.stestate
直接使用数据需要调用this.state.xxx使用数据

对比代码示例:?

?类组件:

import React, { Component } from 'react'

export default class classComponent extends Component {
    constructor(props){
        super(props)
        /**
         * 初始化:需要赋值
         */
        this.state={
            counter:100
        }
    }

    handleClick = ()=>{
        /**
         * 更改数据:需要使用setState({})
         */
        this.setState({counter:200})
    }

    render() {
        //  const {counter} = this.state
        return (
            <div>
                class组件
                {/* 使用:如果不解构,需要调this.state */}
            <p>{this.state.counter}</p>
            <button onClick={this.handleClick}>修改</button>
            </div>
        )
    }
}

函数组件(hook):

import React,{useState} from "react";

 const HookComponent = ()=>{
     
     /**
      * 初始化:useState(100) 括号里的就是初始值
      */
     const [counter,setCount] =useState(100)

     function handleClick (){
        /**
         * 更改数据:直接调用setCount
         */
        setCount(2000) //改数据
     }
    return (
        <div>
            <p>hook</p>
            {/* 使用:直接访问*/}
            <p>{counter}</p>
            <button onClick={handleClick}></button>
        </div>
    )
}
export default HookComponent

Effect Hook

在类组件,我们传统初始化数据的时候会放在生命周期函数里面,比如componentDidMount

import React, { Component } from 'react'

export default class classComponent extends Component {
    constructor(props){
        this.state={
            counter:100
        }
    }

    //初始化数据
    componentDidMount(){
        console.log(11)
    }

    render() {
        return (
            <div>
                class组件
            </div>
        )
    }
}

但是函数组件没有生命周期函数,这时候就可以使用useEffect()了。

它可以理解为三个生命周期函数componentDidMount / componentDidUpdate / componentWillUnmount的组合。

可是一个函数怎么代替三个生命周期呢?

  • 在数据更新和卸载时都会调用?useEffect()

为什么三个生命要放一起?

  • 如果业务很多,由于生命周期各只有一个,所以生命周期函数会写很长。
  • 但是useEffect可以写很多个,不限制。相当于把一个生命周期函数里边的业务代码分离了,代码组织能力变强了
  • 每一个useEffect都可以处理一个独立的业务

作为?componentDidMount

比如我们需要在网络请求在初始化之后进行赋值

import React,{useState, useEffect} from "react";
import axios from "axios";
const UseEffectComponent = ()=>{
    const [data,setData] = useState({})

    //网络请求在初始化之后进行赋值,赋值后又会一直调用useEffect,会一直刷新,效率很低
    useEffect(()=>{
        axios.get('xxx').then(res=>{
            setData(res.data)
        })
    })
    return (
        <div>
            effect应用
            <p>{data}</p>
        </div>
    )
}
export default UseEffectComponent

刚刚说过,在数据更新会调用?useEffect(),那么这里会出现一个问题,请求成功后赋值就相当于更新了数据,又会一直调用useEffect,会一直刷新,这样也不是办法呀!

这个时候,就出现了useEffect()的第二个参数,[ ]

只要在useEffect()加入[ ]作为第二个参数,就代表componentDidMount?,只执行一次

作为componentDidUpdate

? ? ? ? 这个第二个参数里是可以写其他属性值的,如果第二个参数里有值,代表这个值改变就会触发这个方法执行

? ? ? ? 以下代码实现:count变,打印一次

import React,{useState, useEffect} from "react";
import axios from "axios";
const UseEffectComponent = ()=>{
    const [data,setData] = useState({})
    const [count,setCount] = useState(0)

    useEffect(()=>{
        // axios.get('').then(res=>{
        //     setData(res.data)
        // })
        console.log(111111)
    },[count]) //监听count

    function clickHandle(){
        setCount(count+1) //点一次按钮,count+1
    }
    
    return (
        <div>
            effect应用
            {/* <p>{data}</p> */}
            <button onClick={clickHandle}>count+1</button>
            {count}
        </div>
    )
}
export default UseEffectComponent

作为componentWillUnmount

????????这就需要讲讲useEfeect的副作用

useEfeect副作用

? ? ? ? 添加订阅、设置定时器、记录日志都属于副作用,比如设置定时器,我们在useEffect里放了一个定时器,每一秒打印

useEffect(()=>{
    timer = setInterval(()=>{console.log(new Date())},1000) //一秒打印一次
})

????????这样在跳转其他页面的时候还是会继续打印,这就是副作用。这些副作用都是不被允许的,因为这可能会产生莫名其妙的 bug 并破坏 UI 的一致性,需要在组件销毁的时候移除掉

所以需要这在useEfeect后面加上return,清除副作用

useEffect(()=>{
    timer = setInterval(()=>{console.log(new Date())},1000) //一秒打印一次
    //return清除副作用
    return ()=>{
        clearInterval(timer) 
    }
})

完整例子(显示定时器):

import React,{useState,useEffect} from "react"
const TimerApi ={
    time:'',
    subscribe(cb){
        this.timer =setInterval(()=>{
            this.time = new Date().toString()
            cb(this.time)
        }) 
    },
    unsubscribe(){
        clearInterval(this.timer) //清除副作用
    }
}

const EffctClear = ()=>{
    
    const [showTime,setShowTime] = useState('')
    
    useEffect(()=>{
        console.log('调用useEffect')
        TimerApi.subscribe((time)=>{
            setShowTime(time)
        })
        return ()=>{ //清除副作用
            TimerApi.unsubscribe()
        }
    },[]) //只设置一个定时器

    return (
        <div>
            副作用
            {showTime}
        </div>
    )
}
export default EffctClear

useEffect总结

????????useEffect作为componentDidMount?

useEffect(()=>{ },[])

????????useEffect作为componentDidUpdate?

useEffect(()=>{ },[count])

????????useEffect作为componentWillUnmount

useEffect(()=>{ 
    ...
    return ()=>{ ... } 
},[])

?Hook规则

了解了state Hook和effect Hook,说一下hook规则。

1、只在最顶层使用 Hook

??????? 不要在循环,条件或嵌套函数中调用 Hook, 确保是在React函数的最顶层调用他们。

??????? 比如这样是不行的:

//函数内
fuction test(){
    const [data,setData] = useState(0)  //错误
    useEffect(()=>{})   //错误
}

//判断
if(true){
    const [data,setData] = useState(0)  //错误
    useEffect(()=>{})   //错误    
}

//for循环
for(){
    const [data,setData] = useState(0)  //错误
    useEffect(()=>{})   //错误
}

//useEffect()
useEffect(()=>{
    const [data,setData] = useState(0)  //错误  
})

????????需要这样:

const component = ()=>{
    const [data,setData] = useState(0)  //正确

    function test(){}

    return ()
}
export default component

?如果我们想要有条件地执行一个 effect,可以将判断放到 Hook 的内部

  useEffect(function persistForm() {
    // 👍 将条件判断放置在 effect 中
    if (name !== '') {
      localStorage.setItem('formData', name);
    }
  });

2、只在react函数中调用hook

??????? 。。。其他地方也没有hook给你调用

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-28 12:18:13  更:2021-10-28 12:20:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/26 5:06:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码