Hooks

1|0Hooks 基本介绍

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 函数中调用。

2|0useState 和 useEffect

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("执行副作用函数"); },[]);

3|0自定义 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;

__EOF__

本文作者shmillly959
本文链接https://www.cnblogs.com/shmillly959/p/18164706.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   shmillly959  阅读(21)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示