React 第七章 Hooks

news/2024/7/15 19:33:23 标签: react.js, 前端, 前端框架

Hooks 基本介绍

HookReact 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

Hooks 的出现,首先能解决如下的一些问题:

  • 告别令人疑惑的生命周期
    • 例如下面的例子,相同的代码在不同的生命周期中存在了两份
import React from "react";

// 类组件
class App extends React.Component {

  constructor() {
    super();
    this.state = {
      count : 0
    }
  }

  componentDidMount(){
    document.title = `你点击了${this.state.count}次`;
  }

  componentDidUpdate(){
    document.title = `你点击了${this.state.count}次`;
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    )
  }
}

export default App;

  • 告别类组件中烦人的 this
    • 在类组件中,会存在 this 的指向问题,例如在事件处理函数中,不能直接通过 this 获取组件实例,需要修改 this 指向
  • 告别繁重的类组件,回归前端程序员更加熟悉的函数

另外,Hooks 的出现,还有更加重要的一个信号,那就是整个 React 思想上面的转变,从“面向对象”的思想开始转为“函数式编程”的思想。这是编程范式上面的转变。

编程范式:

  • 命令式编程:告诉计算机怎么做(How),我们需要给计算机指明每一个步骤
    • 面向过程
    • 面向对象
  • 声明式编程:告诉计算机我要什么(What
    • 函数式编程
    • DSL(领域专用语言,HTML、CSS、SQL

声明式编程并不是新的产物,它是和命令式编程同期出现的。但是,早期更加流行命令式编程。不过随着近几年整个项目工程越来越复杂,以前的命令式编程就有点力不从心,所以现在慢慢开始流行声明式编程。

因此当你学习 Hooks 的时候,会发现突然多了一些以前不熟悉的概念,例如:纯函数、副作用、柯里化、高阶函数等概念。

当然,你可能好奇“面向对象”和“函数式编程”有什么区别,这里推荐一篇文章:

https://www.imaginarycloud.com/blog/functional-programming-vs-oop/

Hook 就是 JavaScript 函数,但是使用它们会有两个额外的规则:

  • 只能在函数最外层调用 Hook。不要在循环、条件判断或者子函数中调用。
  • 只能在 React 的函数组件中调用 Hook。不要在其他 JavaScript 函数中调用。

useStateuseEffect

React 内置了一些实用的 Hook,并且随着 React 版本的更新,Hook 的数量还在持续增加当中。

入门阶段,我们掌握两个最常用的 Hook,一个是为函数组件添加状态的 useState,另一个是处理函数副作用的 useEffect

useState

  • 基本使用
import { useState } from 'react';

function App(props) {

  let [count, setCount] = useState(0);

  function clickhandle(){
    setCount(++count);
  }

  return (
    <div>
      <div>{count}</div>
      <button onClick={clickhandle}>+1</button>
    </div>
  );
}

export default App;

  • 声明多个 state 状态
import { useState } from 'react';

function App(props) {

  let [age, setAge] = useState(18);
  const [fruit, setFruit] = useState('banana');
  const [todos, setTodos] = useState([{ text: '学习 Hook' }]);

  function clickhandle(){
    setAge(++age);
  }


  return (
    <div>
      <div>年龄:{age}</div>
      <div>水果:{fruit}</div>
      <div>待办事项:{todos[0].text}</div>
      <button onClick={clickhandle}>+1</button>
    </div>
  );
}

export default App;

useEffect 包含以下知识点:

  • 副作用的概念

    • 纯函数:一个确切的参数在函数运行结束,可以得到一个确切的值,例如下面的例子:
    function test(x){
      return x * 2;
    }
    
    x => 2 ===> 4
    x => 3 ===> 6
    
    • 如果一个函数中,存在副作用,那么我们就称该函数不是一个纯函数,所谓副作用,就是指函数的结果是不可控,不可预期。
    • 常见的副作用有发送网络请求、添加一些监听的注册和取消注册,手动修改 DOM,以前我们是将这些副作用写在生命周期钩子函数里面,现在就可以书写在 useEffect 这个 Hook 里面
  • 基本使用

import { useState, useEffect } from 'react';

function App() {

  let [count, setCount] = useState(0);

  useEffect(()=>{
    // 书写你要执行的副作用,会在组件渲染完成后执行
    document.title = `你点击了${count}次`;
  });


  function clickhandle() {
    setCount(++count);
  }

  return (
    <div>
      <div>你点击了{count}次</div>
      <button onClick={clickhandle}>+1</button>
    </div>
  );
}

export default App;
  • 执行清理工作
import { useState, useEffect } from 'react';

function App() {

  let [count, setCount] = useState(0);

  useEffect(()=>{
    // 书写你要执行的副作用,会在组件渲染完成后执行
    const stopTimer = setInterval(()=>{
      console.log("Hello");
    },1000)   

    // console.log("副作用函数执行了");
    // 在 useEffect 中,可以返回一个函数,该函数我们称之为清理函数(一般就是做一些清理操作)
    // 该函数会在下一次渲染之后,但是在执行副作用操作之前执行
    return ()=>{
      // console.log("清理函数执行了");
      clearInterval(stopTimer);
    }
  });


  function clickhandle() {
    setCount(++count);
  }

  return (
    <div>
      <div>你点击了{count}次</div>
      <button onClick={clickhandle}>+1</button>
    </div>
  );
}

export default App;
  • 副作用的依赖

    • 目前,我们的副作用函数,每次重新渲染后,都会重新执行,有些时候我们是需要设置依赖项,传递第二个参数,第二个参数为一个依赖数组
    import { useState, useEffect } from 'react';
    
    function App() {
    
      let [count1, setCount1] = useState(0);
      let [count2, setCount2] = useState(0);
      let [count3, setCount3] = useState(0);
    
      useEffect(()=>{
        console.log("执行副作用函数");
      },[count1]);
    
      return (
        <div>
          <div>count1:{count1}</div>
          <div>count2:{count2}</div>
          <div>count3:{count3}</div>
          <button onClick={()=>setCount1(++count1)}>+1</button>
          <button onClick={()=>setCount2(++count2)}>+1</button>
          <button onClick={()=>setCount3(++count3)}>+1</button>
        </div>
      );
    }
    
    export default App;
    
    • 如果想要副作用只执行一次,传递第二个参数为一个空数组
    useEffect(()=>{
      console.log("执行副作用函数");
    },[]);
    

自定义 Hook

除了使用官方内置的 Hook,我们还可以自定义 Hook,自定义 Hook 的本质其实就是函数,但是和普通函数还是有一些区别,主要体现在以下两个点:

  • 自定义 Hook 能够调用诸如 useStateuseRef 等,普通函数则不能。由此可以通过内置的 Hooks 获得 Fiber 的访问方式,可以实现在组件级别存储数据的方案等。
  • 自定义 Hooks 需要以 use 开头,普通函数则没有这个限制。使用 use 开头并不是一个语法或者一个强制性的方案,更像是一个约定。

App.jsx

import { useState } from 'react';
import useMyBook from "./useMyBook"

function App() {

  const {bookName, setBookName} = useMyBook();
  const [value, setValue] = useState("");


  function changeHandle(e){
    setValue(e.target.value);
  }

  function clickHandle(){
    setBookName(value);
  }

  return (
    <div>
      <div>{bookName}</div>
      <input type="text" value={value} onChange={changeHandle}/>
      <button onClick={clickHandle}>确定</button>
    </div>
  )
  
}

export default App;

useMyBook

import { useState } from "react";

function useMyBook(){
    const [bookName, setBookName] = useState("React 学习");
    return {
        bookName, setBookName
    }
}

export default useMyBook;

http://www.niftyadmin.cn/n/5411015.html

相关文章

Linux:kubernetes(k8s)pod的基础操作(6)

Linux&#xff1a;kubernetes&#xff08;k8s&#xff09;允许在任意节点使用kubectl命令&#xff08;5&#xff09;-CSDN博客https://blog.csdn.net/w14768855/article/details/136460090?spm1001.2014.3001.5501 我在前两张进行了基础环境的一系列搭建&#xff0c;现在就正…

docker安装和使用kafka

1. 启动zookeeper Kafka依赖zookeeper, 首先安装zookeeper -p&#xff1a;设置映射端口&#xff08;默认2181&#xff09; docker run --name zookeeper \--network app-tier \-e ALLOW_ANONYMOUS_LOGINyes \--restartalways \-d bitnami/zookeeper:latest2. 启动kafka docker…

iOS基础开发介绍

iOS基础开发介绍 iOS是由苹果公司开发的移动操作系统&#xff0c;专为iPhone、iPad和iPod touch等设备设计。iOS系统以其流畅的用户体验、丰富的功能和强大的安全性而著称&#xff0c;成为全球最受欢迎的移动操作系统之一。iOS基础开发则是构建在这些设备上的应用程序的过程&a…

大数据开发-Hadoop之MapReduce

文章目录 MapReduce原理剖析MapReduce之Map阶段MapReduce之Reduce阶段WordCount分析多文件WordCount分析 实战wordCount案例开发 MapReduce原理剖析 MapReduce是一种分布式计算模型,主要用于搜索领域&#xff0c;解决海量数据的计算问题MapReduce由两个阶段组成&#xff1a;Ma…

6. Gin集成redis

文章目录 一&#xff1a;连接Redis二&#xff1a;基本使用三&#xff1a;字符串四&#xff1a;列表五&#xff1a;哈希六&#xff1a;Set七&#xff1a;管道八、事务九&#xff1a;示例 代码地址&#xff1a;https://gitee.com/lymgoforIT/golang-trick/tree/master/14-go-redi…

无人机生态环境监测、图像处理与GIS数据分析

构建“天空地”一体化监测体系是新形势下生态、环境、水文、农业、林业、气象等资源环境领域的重大需求&#xff0c;无人机生态环境监测在一体化监测体系中扮演着极其重要的角色。通过无人机航空遥感技术可以实现对地表空间要素的立体观测&#xff0c;获取丰富多样的地理空间数…

电脑蓝牙在哪里打开?不同系统详解

在现代计算机的多功能性中&#xff0c;蓝牙技术的广泛应用使得我们能够轻松连接各种外部设备&#xff0c;实现无线传输和分享。无论是连接无线耳机、键盘&#xff0c;还是与其他设备快速交换文件&#xff0c;蓝牙在电脑中的角色很重要。然而&#xff0c;对于一些用户而言&#…

Flink 大数据 学习详情

参考视频&#xff1a; 尚硅谷大数据Flink1.17实战教程从入门到精通_哔哩哔哩_bilibili 核心目标&#xff1a; 数据流上的有状态的计算 具体说明&#xff1a; Apache Flink是一个 框架 和 分布式处理引擎&#xff0c;用于对 无界&#xff08;eg&#xff1a;kafka&#xff09; 和…