回老家做PHP网站,百度投广告怎么收费,成都餐饮网站建设,重庆网站开发服务器上一节传送门#xff1a;ReactTS 从零开始教程#xff08;3#xff09;#xff1a;useState
源码链接#xff1a;https://pan.quark.cn/s/c6fbc31dcb02
上一节#xff0c;我们已经学会了React的第一个Hook#xff1a;useState。 这一节#xff0c;我们要学习的是另一…上一节传送门ReactTS 从零开始教程3useState
源码链接https://pan.quark.cn/s/c6fbc31dcb02
上一节我们已经学会了React的第一个HookuseState。 这一节我们要学习的是另一个非常重要的HookuseEffect。 Effect在这里意为副作用 不论是哪一个Hook都是写在函数里面的比如上个章节中useEffect就是写在一个函数中。
import React, { useState } from react;const Switch () {//每一个变量都要单独做一个State//useState解构出两个变量一个是变量名一个是赋值这个变量的函数const [on,setOn] useState(false)return (h2 onClick{ () {setOn(!on)}}{on?关闭:开启}/h2/)
}export default Switch;所以这个副作用就是函数的副作用。 怎么理解呢我们知道函数就是你给我参数我给你一个确定的返回这个叫函数。但是呢有一些操作其实跟函数的返回没有太大的关系却出现在了函数体中比如网络请求订阅事件等这些跟函数渲染不相关就可以被认为是副作用。
两种常见的副作用。
不需要清除的副作用
我们希望在React更新DOM之后发送一些网络请求手动变更DOM记录日志等这些操作在我们函数返回之后完全可以忽略掉。 这些情形就是不需要清除的副作用。 总之当React函数式组件return了一个DOM并成功在页面更新之后如果你还想做一些快活的事情就写在useEffect的第一个回调参数里。 在Switch.tsx中写上如下代码
//以下的effect操作会在DOM更新之后发生
useEffect(() {document.title DOM更新完毕Effect发生
});useEffect接收一个回调函数里面定义了DOM更新完成之后的操作或者说给组件添加了一个渲染后的副作用。 App.tsx 刷新页面 页面的标题发生了变化符合预期。 注意useEffect会在每次渲染后都执行1次。 之前用Class组件的时候分挂载和更新两个钩子所以我们想用这种DOM更新后的操作的话就得在这两个钩子中各写一遍逻辑很麻烦。 现在有了useEffect就化繁为简了。 而且非常好懂。
需要清除的副作用
有些副作用是需要被清除的比如事件的添加。 在 之前做法中我们是在componentDitMount中添加事件然后在componentWillUnmount中解绑事件。 现在我们用useEffect该如何实现呢 我们新创建一个组件叫MouseTracker。 顾名思义就是一个鼠标位置的追踪器。 然后引入React依赖
import React, { useEffect, useState } from react;声明一下函数组件
const MouseTracker : React.FC () {}然后定义坐标状态
//定义坐标const [pos,setPos] useState({x:0,y:0})直接return
return (pX: {pos.x} , Y:{pos.y}/p
)导出去
export default MouseTracker;然后在App.tsx中引入这个组件 目前这个x和y还是静态的都是0我们希望每次鼠标点击的时候就更新这个坐标。 什么时候更新呢首先是鼠标点击之后然后触发x和y的更新也就是dom的更新。 让我们在MouseTracker中添加一个effect
//事件绑定
useEffect(() {const bindCallback (e:MouseEvent) {console.log(鼠标点击了)setPos({x:e.clientX,y:e.clientY}) }//绑定click事件document.addEventListener(click,bindCallback)
})现在页面是这样的 我点一次 再点一次 再点一次 每次点击都会增加N的effect次数。为什么呢因为useEffect会在每次dom更新后触发而我们添加了点击事件后没有及时地去清除所以之前的点击事件还存在导致每次更新后所有的点击事件都触发了effect。 怎么解决呢 我们看下useEffect的源码 /*** Accepts a function that contains imperative, possibly effectful code.** param effect Imperative function that can return a cleanup function* param deps If present, effect will only activate if the values in the list change.** version 16.8.0* see {link https://react.dev/reference/react/useEffect}*/function useEffect(effect: EffectCallback, deps?: DependencyList): void;可以看到这个函数的第一个参数callback并不是一定为void也允许我们返回一个函数。 param effect Imperative function that can return a cleanup function 意思很明确了它允许我们返回一个cleanup function也就是清除函数。 我们修改一下代码
//事件绑定
useEffect(() {const bindCallback (e:MouseEvent) {console.log(鼠标事件绑定)setPos({x:e.clientX,y:e.clientY}) }//绑定click事件document.addEventListener(click,bindCallback)return () {document.removeEventListener(click,bindCallback)}
})我连续点击了四次符合预期。 怎么限制Effect
上面的例子告诉我们只有一重新渲染effect必执行这可能会带来一些性能问题有什么办法对effect做限制嘛 再来看源码 /*** Accepts a function that contains imperative, possibly effectful code.** param effect Imperative function that can return a cleanup function* param deps If present, effect will only activate if the values in the list change.** version 16.8.0* see {link https://react.dev/reference/react/useEffect}*/function useEffect(effect: EffectCallback, deps?: DependencyList): void;这次我们重点看第二个参数 param deps If present, effect will only activate if the values in the list change. 第二个参数是一个数组如果数组里面的任何一项发生变化就会触发effect的执行。 刚才的例子中我们每次点击鼠标就会触发一次事件的绑定和卸载实在是有点太浪费了。 我们希望在组件加载的时候绑定一次就行了然后在组件卸载的时候再解绑。
useEffect(() {console.log(点击事件绑定)const bindCallback (e:MouseEvent) {console.log(鼠标点击了)setPos({x:e.clientX,y:e.clientY}) }//绑定click事件document.addEventListener(click,bindCallback)return () {console.log(点击事件解绑)document.removeEventListener(click,bindCallback)}
},[])我添加一个空数组代表这个effect不依赖于任何state和props只跟组件的安装和卸载有关。 然后修改App.tsx省略页面其他代码
import React,{useState} from react;
import MouseTracker from ./components/MouseTracker;function App() {let [showMouseTracker,setShowMouseTracker] useState(true)return (div classNameAppdivbutton onClick{() {setShowMouseTracker(!showMouseTracker)}}{showMouseTracker ? 关闭鼠标追踪: 打开鼠标追踪}/button/div{showMouseTracker MouseTracker /}/div);
}export default App;
刷新页面 多点几次 点击关闭按钮 页面卸载事件解绑了。 如果你希望这个effect只依赖某一个State将对应的变量填入这个数组即可有多个就填多个。
本节我们学会了useEffect的用法。