有时组件中的数据需要与外部系统的数据或操作同步,React提供了Hook Effect。

Effect 会在组件渲染后运行一些代码,以便将组件与 React 之外的某些系统同步,包比如浏览器 API、第三方小部件,以及网络请求等。

如以下的video播放器的简单加载:

// 声明 Effect
import { useEffect, useRef } from 'react';
/*
* src:来自父组件的props,视频资源的地址
* isPlaying:来自父组件的props,视频是否播放,boolean值
* */
function VideoPlayer({ src, isPlaying }) {
const ref = useRef(null);
/*
Effect 依赖 isPlaying prop 控制逻辑
如果 isPlaying 在上一次渲染时与当前相同,跳过运行 Effect
如果不添加依赖,组件每次渲染后都会执行 Effect
如果依赖为[],组件只在挂载后执行 Effect */
useEffect(() => {
// 组件渲染之后执行以下代码
// 否则video dom尚未渲染,不存在play() 和 pause()方法
if (isPlaying) {
ref.current.play();
} else {
ref.current.pause();
}
}, [isPlaying]);
// 同步到 React state 的“外部系统”是浏览器媒体 API
return <video ref={ref} src={src} loop playsInline />;
}
export default function App() {
const [isPlaying, setIsPlaying] = useState(false);
return (
<>
<button onClick={() => setIsPlaying(!isPlaying)}>
{isPlaying ? 'Pause' : 'Play'}
</button>
<VideoPlayer
isPlaying={isPlaying}
src="water.mp4"
/>
</>
);
}

有时 Effect 需要指定如何停止、撤销,或者清除它的效果。例如,“连接”操作需要“断连”,“获取”既需要“取消”也需要“忽略”。这时候就需要使用清理函数。

每次重新执行 Effect 之前,React 都会调用清理函数;组件被卸载时,也会调用清理函数。

严格模式时,在开发环境下,Effect出现额外的执行,是 React 正在调试你的代码。

通常的解决办法是实现清理函数,停止或撤销 Effect 正在执行的任何操作。

在生产环境下,Effect只会执行一次。

App.js

import { useState, useEffect } from 'react';
import { createConnection } from './chat.js'; export default function ChatRoom() {
useEffect(() => {
//建立连接
const connection = createConnection();
connection.connect();
//清理函数,断开连接
return () => connection.disconnect();
}, []);
return <h1>欢迎来到聊天室!</h1>;
}

chat.js

export function createConnection() {
// 连接的示例
return {
connect() {
console.log('连接中……');
},
disconnect() {
console.log('连接断开。');
}
};
}

Effect应用举例:

1、订阅事件

如果 Effect 订阅了某些事件,清理函数应该退订这些事件:

useEffect(() => {
function handleScroll(e) {
console.log(window.scrollX, window.scrollY);
}
//页面滚动事件
window.addEventListener('scroll', handleScroll);
//清理页面滚动事件
return () => window.removeEventListener('scroll', handleScroll);
}, []);

2、触发动画

如果 Effect 对某些内容加入了动画,清理函数应将动画重置:

useEffect(() => {
const node = ref.current;
node.style.opacity = 1; // 触发动画
return () => {
node.style.opacity = 0; // 重置为初始值
};
}, []);

3、获取数据

如果 Effect 将会获取数据,清理函数应该要么终止数据获取操作,要么忽略其结果:

useEffect(() => {
let ignore = false; async function startFetching() {
const json = await fetchTodos(userId);
//不忽略结果,更新数据
if (!ignore) {
setTodos(json);
}
} startFetching(); return () => {
ignore = true;
};
}, [userId]);

还有一些情形看似需要使用 Effect 实则并不需要,比如:初始化应用时,某些逻辑只需要在应用程序启动时运行一次。比如,验证登陆状态和加载本地程序数据,可以将其放在组件之外:

if (typeof window !== 'undefined') { // 检查是否在浏览器中运行
checkAuthToken();
loadDataFromLocalStorage();
} function App() {
// ……
}

React Hook 之 Effect :同步与外部系统的数据的更多相关文章

  1. GraphQL + React Apollo + React Hook 大型项目实战(32 个视频)

    GraphQL + React Apollo + React Hook 大型项目实战(32 个视频) GraphQL + React Apollo + React Hook 大型项目实战 #1 介绍「 ...

  2. React Hook:使用 useEffect

    React Hook:使用 useEffect 一.描述 二.需要清理的副作用 1.在 class 组件中 2.使用 effect Hook 的示例 1.useEffect 做了什么? 2.为什么在组 ...

  3. 使用React Hook后的一些体会

    一.前言 距离React Hook发布已经有一段时间了,笔者在之前也一直在等待机会来尝试一下Hook,这个尝试不是像文档中介绍的可以先在已有项目中的小组件和新组件上尝试,而是尝试用Hook的方式构建整 ...

  4. React Hook上车

    React Hook 是 v16.8 的新功能,自诞生以来,受到广泛的好评,在 React 版本更新中具有里程碑的意义.现在都2020年了,再不上车 React Hook 就真的 out 了... H ...

  5. React Hook Flow Diagram

    一.概述 Donovon has created this nice flowchart that explains the new lifecycle of a Hooks component. C ...

  6. 【翻译】Flink Table Api & SQL —— 连接到外部系统

    本文翻译自官网:Connect to External Systems  https://ci.apache.org/projects/flink/flink-docs-release-1.9/dev ...

  7. React Hook挖坑

    React Hook挖坑 如果已经使用过 Hook,相信你一定回不去了,这种用函数的方式去编写有状态组件简直太爽啦. 如果还没使用过 Hook,那你要赶紧升级你的 React(v16.8+),投入 H ...

  8. 【译】值得推荐的十大React Hook 库

    十大React Hook库 原文地址:https://dev.to/bornfightcompany/top-10-react-hook-libraries-4065 原文作者:Juraj Pavlo ...

  9. Akka(25): Stream:对接外部系统-Integration

    在现实应用中akka-stream往往需要集成其它的外部系统形成完整的应用.这些外部系统可能是akka系列系统或者其它类型的系统.所以,akka-stream必须提供一些函数和方法来实现与各种不同类型 ...

  10. Dynamics CRM2013 从外部系统取到CRM系统的用户头像

    CRM从2013开始引入了entityimage的概念,具体这个字段怎么设置的,图像是怎么上传的这里就不谈了.说实在的这玩意在项目中没啥用,所以也没去关注,直到最近遇到了个难题,要在外部系统去获取这个 ...

随机推荐

  1. 「codeforces - 868F」Yet Another Minimization Problem

    link. 值域分治优化决策单调性 DP 的 trick.朴素做法 trivial,不赘述. 考虑求取一个区间 \([l,r]\) 的 DP 值.先搞定在 \(m=\lfloor\frac{l+r}{ ...

  2. Solution Set -「ABC 193」

    「ABC 193A」Discount Link. 略. #include<cstdio> int main() { int a,b; scanf("%d %d",&am ...

  3. OPPO主题组件开发 - 调试与预览

    本篇作为 OPPO主题组件调试与预览 文档的补充,因为它真的很简单而且太老,一些命令已发生变化 1. 调试前准备 1. PC 端下载 adb命令工具 下载 https://adbdownload.co ...

  4. 开源.NetCore通用工具库Xmtool使用连载 - 扩展动态对象篇

    [Github源码] <上一篇> 介绍了Xmtool工具库中的图形验证码类库,今天我们继续为大家介绍其中的扩展动态对象类库. 扩展动态对象是整个工具库中最重要的一个设计.在软件开发过程中, ...

  5. oracle优化-分页查询新认识

    在写这篇文章之前,对分页查询的认识就是经典的三层嵌套:第①层:获得需要的数据,第②层:用rownum限制展示数据的上限,第③层:用rownum的别名rn限制展示数据的下限. 在生产中遇见一个两层嵌套满 ...

  6. 一些对dp突然的理解

    突然想到了一些理解,感觉有些模糊,怕忘记,就赶紧记下来就是对于状态的设计 用01背包举例子吧,我们设计状态的时候一定是要保证所有可能在最后优秀的子状态在前面的时候是能够保留下来的也就是我们的状态设计要 ...

  7. CF1878 A-G 题解

    前言 赛时代码可能比较难看. 为什么 Div3 会出 4 道数据结构. A 判定 \(a\) 中是否有 \(k\) 即可. 赛时代码 B 奇怪的构造题. 令 \(a_1=1,a_2=3\),其他项由上 ...

  8. 15. 从零开始编写一个类nginx工具, 如果将nginx.conf转成yaml,toml,json会怎么样

    wmproxy wmproxy将用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器,后续将实现websocket代理, 内外网穿透等, 会将实现过程分享出来, 感 ...

  9. React技术栈支援Vue项目,你需要提前了解的

    写在前面 react整体是函数式的思想,把组件设计成纯组件,状态和逻辑通过参数传入,而vue的思想是响应式的,也就是基于是数据可变的,通过对每一个属性建立Watcher来监听, 当属性变化的时候,响应 ...

  10. 初识FreeRTOS

    FreeRTOS是一个迷你的实时操作系统内核.作为一个轻量级的操作系统,功能包括:任务管理.时间管理.信号量.消息队列.内存管理.记录功能.软件定时器.协程等,可基本满足较小系统的需要.   一.Fr ...