ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

react19【系列实用教程】useEffect —— 副作用操作

react19【系列实用教程】useEffect —— 副作用操作 什么是副作用操作在程序中副作用指的是 一个函数除了返回值之外还做了其他事情。 纯函数pure function同样的输入 → 永远返回同样的输出不会影响外部世界 有副作用的函数同样的输入 → 可能返回不一样的输出或者改动了外部世界比如改全局变量、发请求、操作 DOMReact 组件的任务就是渲染UI。所以对于React来说它的副作用就是组件在渲染之外做的其他事情。在 React 组件中副作用操作包括但不限于调用接口获取数据API 请求 / fetch / axios修改 DOM例如操作元素样式、位置、焦点等设置定时器setInterval / setTimeout订阅 WebSocket / 事件如监听滚动、广播、键盘输入操作浏览器 API比如 localStorage、sessionStorage、window 对象改变 URL如 window.locationuseEffect 用于编写由渲染本身引起的对接组件外部的操作官方称呼为副作用操作以下情况会触发页面渲染初次加载页面组件挂载响应式变量发生变化触发页面根据新值重新渲染组件更新关闭页面组件卸载以下情况需要添加副作用操作页面初步渲染完成后向服务器获取数据完成页面的最终渲染响应式变量发生变化时先根据新值执行必要的业务逻辑再进行最终的页面更新渲染关闭页面时需清除副作用如清除定时器移除全局事件等。useEffect 语法useEffect 是 hook 函数第一个参数必要 自定义的处理函数官方称呼为副作用函数可在副作用函数中 return 一个函数来清除副作用从第二次执行副作用函数开始每次都会先执行return中的清除副作用的函数再执行副作用函数当组件卸载时所有清除副作用的函数会按顺序依次执行。第二个参数可选 依赖项 不能为对象/数组等引用类型的数据因为引用类型的数据每次页面渲染时都会生成新地址若useEffect的处理函数会引发页面重新渲染则会导致死循环无依赖项执行副作用函数的时机组件初次渲染后组件挂载完成在开发环境会执行两次生产环境仅执行一次组件更新渲染前任一响应式变量变化都会触发import{useEffect}fromreact;functionDemo(){useEffect((){console.log(执行了副作用函数);});return(div你好/div/);}exportdefaultDemo;依赖项为空数组 []类似 vue 的生命周期 mounted执行副作用函数的时机组件初次渲染后组件挂载完成在开发环境会执行两次生产环境仅执行一次import{useEffect}fromreact;functionDemo(){useEffect((){console.log(执行了副作用函数);},[]);return(div你好/div/);}exportdefaultDemo;使用场景初次渲染页面时访问接口加载页面数据import{useEffect,useState}fromreact;importaxiosfromaxios;functionDemo(){const[list,setList]useState([]);useEffect((){asyncfunctiongetList(){constresawaitaxios.get(http://localhost:3000/dataList);setList(res.data);}getList();},[]);return({list.map((item)(div key{item.id}{item.title}/div))}/);}exportdefaultDemo;依赖项为响应式变量构成的数组类似 vue 的立即执行侦听器 watch执行副作用函数的时机组件初次渲染后组件挂载完成在开发环境会执行两次生产环境仅执行一次响应式变量发生变化触发页面进行更新渲染前import{useEffect,useState}fromreact;functionDemo(){const[name,setName]useState(朝阳);useEffect((){// 在挂载和 name 更新时都会执行console.log(当前name值为,name);},[name]);functionchangeName(){setName(晚霞);}return(button onClick{changeName}改名字/button/);}exportdefaultDemo;清除副作用最经典的场景即在组件卸载时清除计时器以免内存泄露清除副作用的逻辑写在 useEffect 内回调函数的 return 后面需要注意的是return 后必须是一个函数father.jsximport{useState}fromreact;importChildfrom./child.jsx;functionFather(){const[ifChild,setIfChild]useState(true);functionremoveChild(){setIfChild(false);}return(button onClick{removeChild}移除子组件/button{ifChildChild/}/);}exportdefaultFather;child.jsximport{useEffect}fromreact;functionChild(){useEffect((){// 添加定时器consttimersetInterval((){console.log(执行了定时器);},1000);return(){// 清除定时器clearInterval(timer);};});return(divh1我是子组件/h1/div/);}exportdefaultChild;如何关闭开发环境执行两次 将 src/main.jsx 中的React.StrictMode /React.StrictMode标签删除即可。useEffect 演示代码可通过下方演示代码在控制台监听查看父子组件副作用函数和清除副作用函数的执行顺序和时机father.jsximport{useEffect,useState}fromreact;importChildfrom./Child.jsx;exportdefaultfunctionFather(){const[showChild,setShowChild]useState(true);const[num,setNum]useState(0);console.log(父组件渲染);useEffect((){console.log(执行了父组件依赖[]的useEffect内的代码);return(){console.log(执行了父组件依赖[]的useEffect中return的函数);};},[]);return(div style{{border:1px solid,padding:10px,margin:10px}}h1父组件/h1pnum为{num}/pbutton onClick{(){setNum(num1);}}1/button{showChildChild/}button onClick{(){setShowChild(false);}}卸载子组件/buttonbutton onClick{(){setShowChild(true);}}挂载子组件/button/div);}Child.jsximport{useEffect,useState}fromreact;functionChild(){const[name,setName]useState(朝阳);console.log(子组件渲染);useEffect((){console.log(执行了子组件无依赖的useEffect内的代码);return(){console.log(执行了子组件无依赖的useEffect中return的函数);};});useEffect((){console.log(执行了子组件依赖 [] 的useEffect内的代码);return(){console.log(执行了子组件依赖 [] 的useEffect中return的函数);};},[]);useEffect((){console.log(执行了子组件中依赖name的useEffect内的代码);return(){console.log(执行了子组件中依赖name的useEffect中return的函数);};},[name]);return(div style{{border:1px solid,padding:10px,margin:10px}}h1子组件/h1p名称为{name}/pbutton onClick{()setName(张三)}改名称/button/div);}exportdefaultChild;
返回列表