import React,{useState} from "react"
只要是副效应,都可以使用useEffect()
引入。
useEffect,就是执行有副作用的操作,默认情况下,它在第一次渲染之后和每次更新之后都会执行。 可以把 useEffect Hook 看做 componentDidMount,componentDidUpdate 和 componentWillUnmount
这三个函数的组合。
作用/用途
注意事项
useEffect()
时,如果有多个副效应,应该调用多个useEffect()
,而不应该合并写在一起。使用步骤
import React,{useEffect} from "react"
示例
import React, { useState, useEffect } from &#39;react&#39;function EffectFunction() {const [num, setNum] &#61; useState(1)//以下函数先输出1&#xff0c;再输出2useEffect(() &#61;> {console.log("2")document.body.addEventListener(&#39;todo&#39;, () &#61;> { })return () &#61;> {document.body.removeEventListener(&#39;todo&#39;, () &#61;> { })console.log("1")}}, [num])return (<div onClick&#61;{() &#61;> setNum(num &#61;> num &#43; 1)}>这是一个函数组件-{num}</div>)
}
export default EffectFunction
作用
注意事项
使用步骤
import React,{useLayoutEffect} from "react"
示例
import React, { useState, useEffect, useLayoutEffect } from &#39;react&#39;function EffectFunction() {const [num, setNum] &#61; useState(1)useLayoutEffect(() &#61;> {console.log("useLayoutEffect")document.body.addEventListener(&#39;layout&#39;, () &#61;> { })return () &#61;> {document.body.removeEventListener(&#39;layout&#39;, () &#61;> { })}}, [num])useEffect(() &#61;> {console.log("useEffect")document.body.addEventListener(&#39;todo&#39;, () &#61;> { })return () &#61;> {document.body.removeEventListener(&#39;todo&#39;, () &#61;> { })}}, [num])return (<div onClick&#61;{() &#61;> setNum(num &#61;> num &#43; 1)}>这是一个函数组件-{num}</div>)}export default EffectFunction
useEffect与useLayoutEffect区别
概述
当父组件因为自身状态改变而重新渲染时&#xff0c;会带动子组件的重新渲染&#xff0c;及时此时子组件的状态并没有发生改变&#xff0c;为了解决子组件的非必要渲染&#xff0c;可以使用memo函数来包装子组件&#xff0c;这样当子组件的props没有发生改变时&#xff0c;及时父组件重新渲染了&#xff0c;子组件也不会重新渲染。
作用
注意事项
使用步骤
import React,{useMemo} from "react"
适用场景
示例
import React, { useState, useEffect, useMemo } from &#39;react&#39;function EffectFunction() {const [num, setNum] &#61; useState(1)const [age, setAge] &#61; useState(18)// function getDoubleNum(){// console.log("获取双倍的num")// return 2 * num// }//useMemo使用方法//1.接收一个函数作为参数//2.第二个参数为依赖列表//3.返回的是一个数值const getDoubleNum &#61; useMemo(()&#61;>{console.log("获取双倍的num")return 2*num},[num])return (<div onClick&#61;{() &#61;> setNum(num &#61;> num &#43; 1)}>这是一个函数组件-{getDoubleNum},age的值为----{age}</div>)
}export default EffectFunction
概述
useRef
返回的 ref 对象在组件的整个生命周期内保持不变&#xff0c;也就是说每次重新渲染函数组件时&#xff0c;返回的ref 对象都是同一个。从概念上讲&#xff0c;可以认为 refs 就像是一个 class 的实例变量。useRef
不仅仅是用来管理DOM ref的它可以存放任何变量&#xff0c;更改.current
属性不会导致重新渲染。作用
注意事项
使用场景
示例
import React, { useState, useEffect, useRef } from &#39;react&#39;function EffectFunction() {const [num, setNum] &#61; useState(1)const ref &#61; useRef()//1.保存一个值&#xff0c;在整个生命周期中维持不变//2.重新赋值ref.current不会触发重新渲染useEffect(() &#61;> {ref.current &#61; setInterval(() &#61;> {setNum(num &#61;> num &#43; 1)}, 400)}, [])useEffect(() &#61;> {if (num > 10) {console.log("超过10了", ref.current)clearInterval(ref.current)}}, [num])return (<div>这是一个函数组件-{num}</div>)
}export default EffectFunction
作用
注意事项
context
api 来实现在组件之间共享此类值的方式&#xff0c;而不必显式地通过组件树的逐层传递 props。React 16.3之后的context
api 较之前的好用Context.Provider
&#xff0c;接收一个 value 属性&#xff0c;传递给消费组件。一个 Provider 可以和多个消费组件有对应关系。多个 Provider 也可以嵌套使用&#xff0c;里层的会覆盖外层的数据使用步骤&#xff08;单数据源、父组件向子组件通信&#xff09;
useContext
、createContext
两个内容createContext
创建一个context句柄Context.Provider
来确定数据共享范围value
来分发内容useContext(context句柄)
来获取数据使用Context.Provider
&#xff0c;具体使用方法如下&#xff1a;
createContext()
创建一个context 对象&#xff08;内容为需要传递的数据&#xff09;&#xff0c;参数为默认值&#xff1b;<.Provider>
将当前 context 的值传递给内部所有的组件树。当使用了 <.Provider>
后&#xff0c;不再读取上面的默认值&#xff0c;需要设置 value 属性来进行数据传递。contextType
读取当前的 context 对象&#xff08;即刚开始创建的 context&#xff09;&#xff1b;useContext(context句柄)
&#xff0c;获取到当前 context 内的数据示例
import React, { useState, useContext, createContext } from &#39;react&#39;//1.需要引入useContext、createContext两个内容
//2.通过createContext创建一个context句柄
//3.Conext.Provider来确定数据共享范围
//4.通过value来分发内容
//5.在子组件中&#xff0c;通过useContext(context句柄)来获取数据const ShowNumContext &#61; createContext(null)
function EffectFunction() {const [num, setNum] &#61; useState(1)return (<div>这是一个函数组件-{num}// 使用Provider 将当前context的值传递给下面的组件树<ShowNumContext.Provider value&#61;{num}><Item1></Item1><Item2></Item2></ShowNumContext.Provider></div>)
}
/*** 子组件1*/
function Item1() {//指定contextType 读取当前的context//react 会往上找到最近的 Provider&#xff0c;然后使用它的值const num &#61; useContext(ShowNumContext)return (<div>子组件{num}</div>)
}/*** 子组件2*/
function Item2() {const num &#61; useContext(ShowNumContext)return (<div>子组件{num &#43; 2}</div>)
}export default EffectFunction
上面的方法中&#xff0c;我们实现了跨组件的数据传递&#xff0c;这种方式的缺点是只能有一个共享的数据源&#xff0c;也就是在 Item1 组件
和Item2组件
中&#xff0c;指定 num的值只能是一个
。那么如果我们有多个数据源都需要进行跨组件传递&#xff0c;应该怎么做呢&#xff1f;可以使用 <.Consumer>
来实现对多个数据源进行共享&#xff08;多数据源跨组件通信&#xff09;
Context的使用场景
Context 主要应用场景在于很多不同层级的组件需要访问同样一些的数据。谨慎使用&#xff0c;因为这会使得组件的复用性变差。如果用组件组合可以解决的问题&#xff0c;就不要使用 Context 。
使用 context 的通用的场景包括管理当前的 locale&#xff0c;theme&#xff0c;或者一些缓存数据。
作用
使用步骤
useReducer(reducer,store)
来获取state和dispatch注意事项
示例
import React, { useReducer } from &#39;react&#39;//redux必须的内容——store&#xff0c;reducer//useReducer使用方法
//1.需要创建 数据仓库store和管理者reducer
//2.通过useReducer(reducer,store)来获取state和dispatch
const store &#61; {num: 10
}
const reducer &#61; (state, action) &#61;> {switch (action.type) {case "changeNum":return {...state,num: action.num}default:return {...state}}
}
function EffectFunction() {const [state, dispatch] &#61; useReducer(reducer, store)return (<div onClick&#61;{() &#61;> {dispatch({type: &#39;changeNum&#39;,num: 100})}}>这是一个函数组件-{state.num}</div>)
}
export default EffectFunction
作用
使用步骤
示例
import React, { useState, useEffect } from &#39;react&#39;
/*** 自定义Hooks步骤* 1.引入react和自己需要的hook* 2.创建自己的hook函数* 3.返回一个数组&#xff0c;数组中第一个内容是数据&#xff0c;第二个是修改数据的函数* 4.将自己定义的hook函数暴露出去* 5.在自己的业务组件中&#xff0c;引入并使用*///如何实现模拟的数据接口请求功能
function userLoadData() {const [num, setNum] &#61; useState(1)useEffect(() &#61;> {setTimeout(() &#61;> {setNum(2)}, 1000)}, [])return [num,setNum]
}
export default userLoadData