React Hooks

2023-11-19

为什么使用 React Hook

6 Reasons to Use React Hooks Instead of Classes

useState hook

  • useState hook用来render state variable
  • 标准写法: const [stateVariable, setStateVariable function] = useState();
import React, { useState } from "react";

const StateTutorial = () => {
  //inputValue是state variable
  //setInputValue是function
  //只能通过setInputValue对state variable进行修改
  const [inputValue, setInputValue] = useState("Pedro"); 

  let onChange = (event) => {
    //因为setInputValue是异步的, 所以需要先将event.target赋值出来
    const newValue = event.target.value;
    setInputValue(newValue);
  };

  return (
    <div>
      <input placeholder="enter something..." onChange={onChange} />
      {inputValue}
    </div>
  );
};

export default StateTutorial;

实现效果: 右边同时更新左边输入的字符串
在这里插入图片描述

实际开发例子:

  • state variable selectedChildren 是一个数组
  • 通过onChange调用setSeelctedChildren, 对selectedChildren进行修改
  • selectedChildren通过value props传给组件, 渲染到屏幕上

在这里插入图片描述
在这里插入图片描述

  • setStateVariable function不是Web API和server call 为什么还是异步的?
  • This is because setState alters the state and causes rerendering. This can be an expensive operation and making it synchronous might leave the browser unresponsive. Thus the setState calls are asynchronous as well as batched for better UI experience and performance.

useReducer hook

  • 当同时需要update多个state时可以使用useReducer
const ReducerTutorial = () => {
	const [count, setCount] = useState(0);
	const [showText, setShowText] = useState(true);
	
	return (
    <div>
      <h1>{state.count}</h1>
      <button
        onClick={() => {
        	setCount(count + 1);
        	setShowText(!showText);
        }}
      >
        Click Here
      </button>

      {state.showText && <p>This is a text</p>}
    </div>
  );
}

上面的代码可以使用useReducer完成, 如下

import React, { useReducer } from "react";

const reducer = (state, action) => {
  switch (action.type) {
    case "INCREMENT":
      return { count: state.count + 1, showText: state.showText };
    case "toggleShowText":
      return { count: state.count, showText: !state.showText };
    default:
      return state;
  }
};

const ReducerTutorial = () => {
  const [state, dispatch] = useReducer(reducer, { count: 0, showText: true });

  return (
    <div>
      <h1>{state.count}</h1>
      <button
        onClick={() => {
          dispatch({ type: "INCREMENT" });
          dispatch({ type: "toggleShowText" });
        }}
      >
        Click Here
      </button>

      {state.showText && <p>This is a text</p>}
    </div>
  );
};

export default ReducerTutorial;

useEffect hook

  • 当每次页面render时, useEffect都会被执行
  • 除去刷新页面外, state variable被rerender时也会执行 useEffect

标准写法:

useEffect(() => { 
	do something ); 
 }, []);    
  • 后面的[]表示哪些state variable被更新时会执行useEffect
  • [ ] 为空表示任何state varibale更新时都不会执行useEffect. 只有按刷新页面时才会执行useEffect
  • 如果没有 [ ] 则表示任何state varibale更新时都会执行useEffect
import React, { useEffect, useState } from "react";
import axios from "axios";

function EffectTutorial() {
  const [data, setData] = useState("");
  const [count, setCount] = useState(0);

//刷新页面时, 会调用API
  useEffect(() => {
    axios
      .get("https://jsonplaceholder.typicode.com/comments")
      .then((response) => {
        setData(response.data[0].email);
        console.log("API WAS CALLED");
      });
  }, []);

  return (
    <div>
      Hello World
      <h1>{data}</h1>
      <h1>{count}</h1>
      <button
        onClick={() => {
          setCount(count + 1);
        }}
      >
        Click![在这里插入图片描述](https://im![在这里插入图片描述](https://img-blog.csdnimg.cn/cc6c700276d04ee084fac886150d282c.png)
g-blog.csdnimg.cn/30669808ec2e4f68b78041512bf23964.png)

      </button>
    </div>
  );
}

export default EffectTutorial;

useRef hook

  • persist values between renderers beside use state. — 也就是在不渲染画面的情况下, 可以在component中储存变量
    在这里插入图片描述
    在这里插入图片描述

useLayoutEffect hook

  • useEffect会在渲染的内容到DOM上后执行,不会阻塞DOM的渲染
  • 也就是先渲染页面 (会显示未更新的state variable), 然后再更新state variable. (因为渲染和更新的非常快, 所以察觉不出来)
  • useLayoutEffect会在渲染的内容到DOM上之前进行,会阻塞DOM的渲染
import { useLayoutEffect, useEffect, useRef } from "react";

function LayoutEffectTutorial() {
  const inputRef = useRef(null);
  
  
  useLayoutEffect(() => {
  //先执行这里
    console.log(inputRef.current.value);
  }, []);
  
  useEffect(() => {
  //再执行这里
    inputRef.current.value = "HELLO";
  }, []);

  return (
    <div className="App">
      <input ref={inputRef} value="PEDRO" style={{ width: 400, height: 60 }} />
    </div>
  );
}

export default LayoutEffectTutorial;

useImperativeHandle hook

  • 可以在上级组件中控制子组件的state
import React, { useRef } from "react";
import Button from "./Button";

function ImperativeHandle() {
  const buttonRef = useRef(null);
  return (
    <div>
      <button
        onClick={() => {
          buttonRef.current.alterToggle();
        }}
      >
        Button From Parent
      </button>
      <Button ref={buttonRef} />
    </div>
  );
}

export default ImperativeHandle;
import React, { forwardRef, useImperativeHandle, useState } from "react";

const Button = forwardRef((props, ref) => {
  const [toggle, setToggle] = useState(false);

  useImperativeHandle(ref, () => ({
    alterToggle() {
      setToggle(!toggle);
    },
  }));
  return (
    <>
      <button>Button From Child</button>
      {toggle && <span>Toggle</span>}
    </>
  );
});

export default Button;

useMemo

  • 用于性能优化
import axios from "axios";
import { useEffect, useState, useMemo } from "react";

export default function MemoTutorial() {
  const [data, setData] = useState(null);
  const [toggle, setToggle] = useState(false);

  useEffect(() => {
    axios
      .get("https://jsonplaceholder.typicode.com/comments")
      .then((response) => {
        setData(response.data);
      });
  }, []);

  const findLongestName = (comments) => {
    if (!comments) return null;

    let longestName = "";
    for (let i = 0; i < comments.length; i++) {
      let currentName = comments[i].name;
      if (currentName.length > longestName.length) {
        longestName = currentName;
      }
    }

    console.log("THIS WAS COMPUTED");

    return longestName;
  };
  
  return (
    <div className="App">
      //这里每当页面渲染, 都会执行这个函数, 如果数据量很大, 会降低性能
      <div> {findLongestName(data)} </div>

      <button
        onClick={() => {
          setToggle(!toggle);
        }}
      >
        {" "}
        Toggle
      </button>
      {toggle && <h1> toggle </h1>}
    </div>
  );
}

使用useMemo改进

import axios from "axios";
import { useEffect, useState, useMemo } from "react";

export default function MemoTutorial() {
  const [data, setData] = useState(null);
  const [toggle, setToggle] = useState(false);

  useEffect(() => {
    axios
      .get("https://jsonplaceholder.typicode.com/comments")
      .then((response) => {
        setData(response.data);
      });
  }, []);

  const findLongestName = (comments) => {
    if (!comments) return null;

    let longestName = "";
    for (let i = 0; i < comments.length; i++) {
      let currentName = comments[i].name;
      if (currentName.length > longestName.length) {
        longestName = currentName;
      }
    }

    console.log("THIS WAS COMPUTED");

    return longestName;
  };

  const getLongestName = useMemo(() => findLongestName(data), [toggle]); //只有当data改变时才执行这个函数

  return (
    <div className="App">
      <div> {getLongestName} </div>

      <button
        onClick={() => {
          setToggle(!toggle);
        }}
      >
        {" "}
        Toggle
      </button>
      {toggle && <h1> toggle </h1>}
    </div>
  );
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

React Hooks 的相关文章

  • 为什么 iife 在一个简单的例子中不起作用?

    我不明白为什么函数表达式调用不起作用并抛出错误 你能给我解释一下吗 var a function x alert x function a 1 谢谢大家 任务比我想象的要容易得多 这是因为 JS 将 IIFE 解析为函数的参数调用 这样做时
  • 在新的 Google 协作平台 <嵌入 HTML> 中使用 localStorage 和 IndexedDB 不起作用

    我正在尝试将新的 Google 协作平台用于我开发的网页 但是 我在存储本地数据时遇到了问题 本地文件在 Windows 和 Apple safari chrome 中运行良好 从 Google 协作平台尝试一下 没有什么乐趣 此外 在 s
  • 如何在故事书中注入窗口变量?

    我想添加一个 React 组件 称为ApplicationForm to a 故事书 https github com storybooks storybook 故事书是这样写的 import configureStore from sto
  • Chrome 中的性能问题

    我目前正在从事一个相对较大的项目 使用 AngularJs 构建 应用程序的一部分是一个表单 您可以向其中添加任意数量的页面 不幸的是 添加了很多不必要的垃圾 即表示表单模型的对象可能会变得非常大 在某些时候 Chrome 基本上无法处理它
  • 如何针对 Node.js 中发生的每个错误发送电子邮件?

    假设我的 node js 应用程序正在运行 如果出现错误 我的意思是所有错误 不仅仅是网络错误 如果出现错误 则很重要 我如何调用函数向我发送电子邮件 基本上 在我希望它写入 err out 之前 我希望向我发送一封电子邮件 我正在使用no
  • 引导程序提前输入未填充承诺的响应

    我的引导程序预输入如下
  • 在打字稿中导入 json

    我是 typescript 的新手 在我的项目中 我们使用 typescript2 在我的要求之一中 我需要导入 json 文件 所以我创建了 d ts 文件如下 test d ts declare module json const va
  • 如何让 Django 和 ReactJS 协同工作?

    New to Django and even newer to ReactJS I have been looking into AngularJS and ReactJS but decided on ReactJS It seemed
  • React-Redux:state.setIn() 和 state.set() 有什么区别?

    我见过使用setIn and set 在一些react redux代码中 state setIn state set 我在这里找到了一些文档https facebook github io immutable js https facebo
  • Chrome 扩展程序在代码中使用 client_secret

    我正在开发具有自己的 oAuth 授权的 Google Chrome 扩展 当然 我必须使用 client id 和 client secret 作为请求令牌 有什么办法可以向用户隐藏这些数据吗 由于此请求只是 javascript 源代码
  • 如何制作没有 ng-repeat 的模板并使用 Angular-drag-and-drop-lists 将数据传递到 $scope?

    我想用角度拖放列表 https github com marceljuenemann angular drag and drop lists使用我自己的网格模板到所见即所得编辑器 如何构建我自己的 HTML 模板而不需要ng repeat因
  • 将 UMD Javascript 模块导入浏览器

    你好 我正在对 RxJS 进行一些研究 我可以通过在浏览器中引用它来使用该库 如下所示 它使用全局对象命名空间变量 Rx 导入 我可以制作可观察的东西并做所有有趣的事情 当我将 src 更改为指向最新的 UMD 文件时 一切都会崩溃 如下所
  • 页面上使用 HTML Editor Extender 进行回发会导致 IE11 中出现 JavaScript 错误

    我已将 HTML 编辑器扩展程序添加到我正在处理的页面中 现在每当我在页面上发回帖子时 都会收到以下 Javascript 错误 JavaScript 运行时错误 参数无效 之后什么也没有发生 这在 IE10 或更低版本以及我所知道的所有其
  • 使用 Vue 的多模式组件

    我在 Vue 中实现动态模式组件时遇到问题 A common approach I follow to display a set of data fetched from the db is I dump each of the rows
  • 如何使用 crypto-js 解密 AES ECB

    我正在尝试将加密数据从 flash 客户端 发送到服务器端的 javascript 在 asp 中作为 jscript 运行 有几个 javascript Aes 库 但它们实际上没有文档记录 我正在尝试使用 crypto js 但无法让代
  • 在 Shopify 商店中嵌入 Vue 组件

    在产品页面中 我尝试显示自定义 Vue 组件 为简洁起见 该组件根据给定的产品 ID 显示 Firebase 数据库中的一些信息 我最初尝试将其制作为 Shopify 应用程序 以便我可以访问他们的 API 我实现了 OAuth 并且可以检
  • Javascript - 水波纹效果

    我需要 JS 上的脚本 它将以 水波纹 样式更改 images html 抱歉 6MB GIF 文件 http fcuunited ru temp listening2 gif http fcunited ru temp listening
  • 用于交互式图形绘制的轻量级 JavaScript 库? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我有兴趣了解用于绘制交互式图表的最轻量级 javascript 库 我掌握的数据主要是与海洋研究相关的科学数据 我知道一些 jquery
  • 如何确定所有角度2分量都已渲染?

    当所有 Angular2 组件完成渲染时 是否会触发一个角度事件 For jQuery 我们可以用 function 然而 对于 Angular2 当domready事件被触发 html 只包含角度组件标签 每个组件完成渲染后 domrea
  • 如何使用asm.js进行测试和开发?

    最近我读到asm js规范 看起来很酷 但是是否有任何环境 工具来开发和测试这个工具 这还只是处于规范阶段吗 您可以尝试使用 emscripten 和 ASM JS 1 并从侧分支在 firefox 构建中运行它 有关 asm js 的链接

随机推荐

  • macbook上的vim怎么设置语法高亮和显示行号

    在我写这篇文章之前我的vim就很普通 没有语法高亮 无法显示行号 但是我通过在网上不断查阅一些处理方法和经验之后 我终于能将我MacBook电脑上的vim配置出语法高亮和显示行号了 作为一名乐于分享 乐于助人的新手程序员 我决定把我的解决办
  • 《Web应用安全权威指南》学习笔记

    第1章 什么是Web应用的安全隐患 第2章 搭建试验环境 邮件发送服务器Postfix POP3服务器Dovecot SSH服务器OpenSSH Web应用调试工具Fiddler 第3章 Web安全基础 HTTP回话管理 同源策略 Cook
  • k8s安全04--kube-apiserver 安全配置

    k8s安全04 kube apiserver 安全配置 1 介紹 2 安全配置 2 1 配置 insecure port 2 2 RBAC 2 3 Service Accounts 2 4 Researching Pod Security
  • Nginx 无法转发本地端口

    问题描述 本文主要分析解决 centos 下 nginx 配置端口转发后不生效 通过 nginx 配置 server 转发后 无法达到预期的转发目的 并出现502错误的问题 假设虚拟机 ip 为 192 168 0 8 并且在虚拟机内部署一
  • ISO七层模型

    物理层 O S I 模型的最低层或第一层 该层包括物理连网媒介 如电缆连线连接器 物理层的协议产生并检测电压以便发送和接收携带数据的信号 在你的桌面P C 上插入网络接口卡 你就建立了计算机连网的基础 换言之 你提供了一个物理层 尽管物理层
  • uni-app项目在微信开发者工具打开时报错[ app.json 文件内容错误] app.json: 在项目根目录未找到 app.json

    uni app项目在微信开发者工具打开时控制台报错 app json 文件内容错误 app json 在项目根目录未找到 app json env Windows mp 1 06 2303220 lib 2 32 0 解决方案 以下是一个u
  • 前端基础之ES6

    1 前后端对比 2 ES6 ECMAScript6 0 以下简称ES6 ECMAScript是一种由Ecma国际通过ECMA 262标准化的脚本 是JavaScript语言的下一代标准 2015年6月正式发布 从ES6开始的版本号采用年号
  • S-DES加密

    S DES加密 Simplified Data Encryption Standard S DES 是一个供教学的非安全的加密算法 它与DES的特性和结构类似 但参数小 明文分组为8位 主密钥分组为10位 采用两轮迭代 S DES加密过程包
  • 第十一讲、FPGA开发中xilinx vivado 平台时序分析系列课程-边沿对齐input delay ddr双沿采样时序约束与收敛

    我们在使用一些以太网PHY和FPGA接口是RGMII接口是DDR双沿结构 还有ADC芯片也也是DDR双沿采样接口 以及CMOS视频传感器也有很多DDR双沿源同步接口 我们这里以IMX222视频传感器的的DDR为例约束input ddr 接口
  • FPGA提示产生latch的报错

    在fpga的设计中有时会遇到 latch 的报错 1 latch是什么 Latch 就是锁存器 是一种在异步电路系统中 对输入信号电平敏感的单元 用来存储信息 锁存器在数据锁存使能时 数据被锁存 输入信号不起作用 这违背了组合逻辑中输出随输
  • selenium元素定位方法 id,name,class

    1 导入selenium from selenium import webdriver from time import sleep 2 打开浏览器 最大化 driver webdriver Chrome driver maximize w
  • Java 学习路线大全,再也不用迷路啦(持续更新)

    路线特点 最新 完整一条龙 从入门到入土 表示推荐学习 给出目标 学习建议 关键知识点 最优资源以及各类资源推荐 视频 书籍 文档 项目 工具等 划分阶段 更有计划 且在最后给出持续学习的方向 探索 Java 程序员发展的无限可能 前言 首
  • SQLSERVER排查CPU占用高的情况

    一般排查都是用下面的脚本 一般会用到三个视图 sys sysprocesses dm exec sessions dm exec requests sys sysprocesses 系统表是一个很重要的系统视图 主要用来定位与解决Sql S
  • 存储类型auto,static,extern,register的区别 <转>

    变量和函数的属性包括数据类型和数据的存储类别 存储类别指数据在内存中存储方式 静态和动态 包含auto static register extern四种 内存中 具体点来说内存分为三块 静态区 堆区 栈区 外部变量和全局变量存放在静态区 局
  • 半监督学习——数据精馏(论文阅读)

    论文地址 https arxiv org pdf 1712 04440 pdf 1 论文与摘要 Data Distillation Towards Omni Supervised Learning 摘要 作者提出一种特殊的半监督学习方法 取
  • android 最新动态,浅谈Android动态页面(一)

    这是一个很微妙的东西 可能平时经常用到 但是没注意 我想对这个内容进行一个总结并提出一些看法 谈的是动态页面 不是动态布局 一 什么是动态页面 什么是动态页面 我认为是一种在开发时的设计思想 最终展示的页面会随着数据的改变而改变 或者说会根
  • OpenCV中如何读取URL图像文件

    点击上方 小白学视觉 选择加 星标 或 置顶 重磅干货 第一时间送达 由来 最近知识星球收到的提问 觉得是一个很有趣的问题 就通过搜集整理归纳了一番 主要思想是通过URL解析来生成数据 转为图像 Mat对象 但是在Python语言与C 语言
  • Java基础学习总结(1)——equals方法

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 一 equals方法介绍 1 1 通过下面的例子掌握equals的用法 1 package cn galc test 2 3 public class TestEquals
  • 简单spring cloud服务升级实现

    1 升级原则 隔离性 v1升级到v2时 相互独立 互不不干扰 稳定性 服务不停止 完成升级 接口保持畅通 2 具体实现 2 1 eureka项目 搭建eureka 网上很多 就省略了 2 2 feign接口项目 2 2 1 依赖
  • React Hooks

    React Hooks 为什么使用 React Hook useState hook useReducer hook useEffect hook useRef hook useLayoutEffect hook useImperative