- ReactJS 教程
- ReactJS 教程
- ReactJS - 简介
- ReactJS - 安装
- ReactJS - 特性
- ReactJS - 优点和缺点
- ReactJS - 架构
- ReactJS - 创建 React 应用程序
- ReactJS - JSX
- ReactJS - 组件
- ReactJS - 嵌套组件
- ReactJS - 使用组件
- ReactJS - 组件集合
- ReactJS - 样式
- ReactJS - 属性(props)
- ReactJS - 使用属性创建组件
- ReactJS - props 验证
- ReactJS - 构造函数
- ReactJS - 组件生命周期
- ReactJS - 事件管理
- ReactJS - 创建事件感知组件
- ReactJS - 在Expense Manager APP中引入事件
- ReactJS - 状态管理
- ReactJS - 状态管理 API
- ReactJS - 无状态组件
- ReactJS - 使用 React Hooks 进行状态管理
- ReactJS - 使用 React 钩子的组件生命周期
- ReactJS - 组件的布局
- ReactJS - 分页
- ReactJS - Material 用户界面
- ReactJS - Http 客户端编程
- ReactJS - 表单编程
- ReactJS - 受控组件
- ReactJS - 不受控制的组件
- ReactJS - Formik
- ReactJS - 条件渲染
- ReactJS - 列表
- ReactJS - 键
- ReactJS - 路由
- ReactJS - 冗余
- ReactJS - 动画
- ReactJS - 引导程序
- ReactJS - 地图
- ReactJS - 表格
- ReactJS - 使用 Flux 管理状态
- ReactJS - 测试
- ReactJS - CLI 命令
- ReactJS - 构建和部署
- ReactJS - 示例
- ReactJS - 钩子简介
- ReactJS - 使用 useState
- ReactJS - 使用 useEffect
- ReactJS - 使用 useContext
- ReactJS - 使用 useRef
- ReactJS - 使用 useReducer
- ReactJS - 使用 useCallback
- ReactJS - 使用 useMemo
- ReactJS - 自定义钩子
- ReactJS - 可访问性
- ReactJS - 代码拆分
- ReactJS - 上下文
- ReactJS - 错误边界
- ReactJS - 转发引用
- ReactJS - 片段
- ReactJS - 高阶组件
- ReactJS - 与其他库集成
- ReactJS - 优化性能
- ReactJS - 分析器 API
- ReactJS - 门户
- ReactJS - 没有 ES6 ECMAScript 的 React
- ReactJS - 没有 JSX 的 React
- ReactJS - 协调
- ReactJS - 引用和 DOM
- ReactJS - 渲染属性
- ReactJS - 静态类型检查
- ReactJS - 严格模式
- ReactJS - Web 组件
- ReactJS - 日期选择器
- ReactJS - Helmet
- ReactJS - 内联样式
- ReactJS - 属性类型
- ReactJS - 浏览器路由器
- ReactJS - DOM
- ReactJS - 旋转木马
- ReactJS - 图标
- ReactJS - 表单组件
- ReactJS - 参考 API
ReactJS - 使用 useEffect
React 提供了 useEffect 来在组件中执行副作用。一些副作用如下 -
- 从外部源获取数据并更新呈现的内容。
- 渲染后更新 DOM 元素。
- 订阅
- 使用计时器
- 伐木
在基于类的组件中,这些副作用是使用生命周期组件完成的。因此,useEffect 钩子是下面提到的生命周期事件的效果替换。
- componentDidMount - 首次渲染完成后触发。
- componentDidUpdate − 由于属性或状态更改而更新渲染后触发。
- componentWillUnmount - 在组件销毁期间卸载渲染内容后触发。
在本章中,让我们学习如何使用效果钩子。
使用效果签名
useEffect的签名如下 -
useEffect( <update function>, <dependency> )
其中,update函数的签名如下:
{
// code
return <clean up function>
}
这里
更新函数 - 更新函数是在每个渲染阶段之后要执行的函数。这对应于 componentDidMount 和 componentDidUpdate 事件
依赖性 - 依赖性是一个数组,其中包含函数所依赖的所有变量。指定依赖关系对于优化效果钩子非常重要。通常,每次渲染后都会调用更新函数。有时没有必要在每次渲染时渲染更新函数。让我们考虑一下,我们正在从外部源获取数据,并在渲染阶段之后更新它,如下所示 -
const [data, setDate] = useState({})
const [toggle, setToggle] = useState(false)
const [id, setID] = useState(0)
useEffect( () => {
fetch('/data/url/', {id: id}).then( fetchedData => setData(fetchedData) )
})
// code
每当数据和切换变量更新时,组件将重新渲染。但正如你所看到的,我们不需要在每次更新切换状态期间运行定义的效果。为了解决这个问题,我们可以传递一个空的依赖项,如下所示 -
const [data, setDate] = useState({})
const [toggle, setToggle] = useState(false)
const [id, setID] = useState(0)
useEffect( () => {
fetch('/data/url/', { id: id }).then( fetchedData => setData(fetchedData) )
}, [])
上述代码在第一次渲染后只会运行一次效果。即使它会修复 issus,也必须在每次更改 id 时运行效果。为了实现它,我们可以将 id 作为效果的依赖项包含在内,如下所示 -
const [data, setDate] = useState({})
const [toggle, setToggle] = useState(false)
const [id, setID] = useState(0)
useEffect( () => {
fetch('/data/url/', { id: id }).then( fetchedData => setData(fetchedData) )
}, [id])
这将确保效果仅在修改 id 后重新运行
清理功能 − 清理功能用于在使用订阅功能和定时器功能时进行清理工作,如下图所示 -
const [time, setTime] = useState(new Date())
useEffect(() => {
let interval = setInterval(() => {
setTime(new Date())
}, 1000)
return () => clearInterval(interval)
}, [time])
让我们创建一个完整的应用程序,以便在后面的部分中理解清理功能。
效果钩的特点
效果钩的一些显着特征如下 -
- React 允许在函数组件中使用多个效果钩子。这将帮助我们为每个副作用编写一个函数,并将其设置为单独的效果。
- 每个钩子都将按照其声明的顺序运行。开发人员应确保正确声明了效果的顺序。
- 依赖性功能可用于提高性能和副作用的正确工作。
- 清理功能可防止内存泄漏和不必要的事件触发。
使用效果获取数据
让我们创建一个应用程序,它将从外部源获取数据,并在本节中使用 useEffect 钩子渲染它。
首先,创建一个新的 react 应用程序并使用以下命令启动它。
cd myapp
npm start
接下来,在组件文件夹 (src/components/NameList.js) 下创建一个 react 组件 NameList
function NameList() {
return <div>names</div>
}
export default NameList
在这里,NameList 组件的目的是展示常用的通用名称列表
接下来,更新根组件,App.js使用新创建的 NameList 组件。
import NameList from "./components/NameList";
function App() {
return (
<div style={{ padding: "5px"}}>
<NameList />
</div>
);
}
export default App;
接下来,创建一个json文件,names.json(public/json/names.json)并以json格式存储热门名称,如下所示。
[
{
"id": 1,
"name": "Liam"
},
{
"id": 2,
"name": "Olivia"
},
{
"id": 3,
"name": "Noah"
},
{
"id": 4,
"name": "Emma"
},
{
"id": 5,
"name": "Oliver"
},
{
"id": 6,
"name": "Charlotte"
},
{
"id": 7,
"name": "Elijah"
},
{
"id": 8,
"name": "Amelia"
},
{
"id": 9,
"name": "James"
},
{
"id": 10,
"name": "Ava"
},
{
"id": 11,
"name": "William"
},
{
"id": 12,
"name": "Sophia"
},
{
"id": 13,
"name": "Benjamin"
},
{
"id": 14,
"name": "Isabella"
},
{
"id": 15,
"name": "Lucas"
},
{
"id": 16,
"name": "Mia"
},
{
"id": 17,
"name": "Henry"
},
{
"id": 18,
"name": "Evelyn"
},
{
"id": 19,
"name": "Theodore"
},
{
"id": 20,
"name": "Harper"
}
]
接下来,创建一个新的状态变量,数据以在NameList组件中存储流行名称,如下所示 -
const [data, setData] = useState([])
接下来,创建一个新的状态变量 isLoading 来存储加载状态,如下所示 -
const [isLoading, setLoading] = useState([])
接下来,使用 fetch 方法从 json 文件中获取流行名称,并将其设置为 useEffect 钩子内的数据状态变量
useEffect(() => {
setTimeout(() => {
fetch("json/names.json")
.then( (response) => response.json())
.then( (json) => { console.log(json); setLoading(false); setData(json); } )
}, 2000)
})
在这里,我们有,
- 使用 setTimout 方法模拟加载过程。
- 使用 fetch 方法获取 json 文件。
- 使用 json 方法解析 json 文件。
- 使用 setData 将从 json 文件解析的名称设置为数据状态变量。
- 使用 setLoading 设置加载状态。
接下来,使用 map 方法呈现名称。在获取过程中,显示加载状态。
<div>
{isLoading && <span>loading...</span>}
{!isLoading && data && <span>Popular names: </span>}
{!isLoading && data && data.map((item) =>
<span key={item.id}>{item.name} </span>
)}
</div>
在这里,我们有,
- 使用 isLoading 显示加载状态
- 使用 data 变量显示热门名称列表
组件 NameList 的完整源代码如下 -
import { useState, useEffect } from "react"
function NameList() {
const [data, setData] = useState([])
const [isLoading, setLoading] = useState([])
useEffect(() => {
setTimeout(() => {
fetch("json/names.json")
.then( (response) => response.json())
.then( (json) => { console.log(json); setLoading(false); setData(json); } )
}, 2000)
})
return (
<div>
{isLoading && <span>loading...</span>}
{!isLoading && data && <span>Popular names: </span>}
{!isLoading && data && data.map((item) =>
<span key={item.id}>{item.name} </span>
)}
</div>
)
}
export default NameList
接下来,打开浏览器并检查应用程序。它将显示加载状态,2秒后,它将获取json并显示流行名称,如下所示 -
DOM 突变
useEffect 钩子可用于使用 DOM 及其方法操作文档。它确保其中的代码仅在 DOM 准备好后才会执行。让我们更改名称列表应用程序并使用 DOM 突变更新页面的标题。
首先,打开 NameList 组件,根据加载状态添加文档标题,如下图所示 -
useEffect(() => {
if(isLoading)
document.title = "Loading popular names..."
else
document.title = "Popular name list"
setTimeout(() => {
fetch("json/names.json")
.then( (response) => response.json())
.then( (json) => { console.log(json); setLoading(false); setData(json);} )
}, 2000)
})
在这里,我们使用了 DOM 对象 document.title 来更新页面的标题。
最后,打开浏览器,检查文档的标题是如何通过DOM操作来更新的
清理功能
useEffect 可用于在从页面文档中卸载组件时删除清理函数,例如 clearInterval、removeEventListener 等。这将防止内存泄漏并提高性能。为此,我们可以创建自己的清理函数,并从 useEffect 回调参数返回它。
让我们更改名称列表应用程序,使用 setInterval 而不是 setTimeout,然后使用 clearInterval 在卸载组件期间删除 set 回调函数。
首先,打开 NameList 组件并更新 useEffect 部分,如下所示 -
useEffect(() => {
if(isLoading)
document.title = "Loading popular names..."
else
document.title = "Popular name list"
let interval = setInterval(() => {
setLoading(true)
fetch("json/names.json")
.then( (response) => response.json())
.then( (json) => { console.log(json); setLoading(false); setData(json);} )
}, 5000)
return () => { clearInterval(interval) }
})
在这里,我们有,
- 使用 setImterval 每 5 秒更新一次热门名称。
- 在清理函数中使用 clearInterval 在卸载组件期间删除 setInterval。
最后,打开浏览器并检查应用程序的行为方式。我们将看到数据每 5 秒更新一次。卸载组件时,将在后台调用 clearInterval。
总结
useEffect 是函数组件的基本特性,它使组件能够使用生命周期事件。它有助于功能组件提供丰富的功能,并具有可预测和优化的性能。