IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> React-Hook -> 正文阅读

[JavaScript知识库]React-Hook

React-Hook

以下内容参考React官网的教程:Hook 简介 – React (docschina.org)

1.Hook简介

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

Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。

使用hook是完全可选的,无需重写之前的任何代码,并不用把所有的类组件重写,而是在新编写的代码中尝试使用hook,或完全不使用。hook是完全向后兼容的,不会影响原有的React概念,反而提供了一种全新的理解方式。

我们使用hook的动机在于,它可以解决一些组件维护方面的问题,在之前,组件间的复用逻辑很难,React需要用render props和高阶组件,容易形成嵌套地狱,而Hook 可以使你在无需修改组件结构的情况下复用状态逻辑,组件之间的共享变得更加便捷。

2.State Hook

通过使用State Hook可以在函数组件里面使用state来储存变量并检测其变化进行动态渲染。(之前只能在class组件里面使用)。

使用方法类似于下面这样:

import React, { useState } from 'react';

function Example() {
  // 声明一个叫 “count” 的 state 变量。
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

function ExampleWithManyStates() {
  // 声明多个 state 变量!
  const [age, setAge] = useState(42);
  const [fruit, setFruit] = useState('banana');
  const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
  // ...
}

在这里useState就是一个Hook,通过这个方法在函数组件里面钩入了内部State,它接收唯一一个参数是初始state值,并有两个返回值。

const后面的写法是数组解构的语法,分别赋予这两个变量对应的返回值。

React内置了一些像useState这样的hook,我们可以直接引入并调用,我们也可以创建自己的Hook,来复用不同组件间的状态逻辑。

3.Effect Hook

useEffect 就是一个 Effect Hook,给函数组件增加了操作副作用1的能力,它跟 class 组件中的componentDidMount、componentDidUpdate 和 componentWillUnmount具有相同的用途,只不过被合并成了一个 API。

使用方法如下:

import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  // 相当于 componentDidMount 和 componentDidUpdate:
  useEffect(() => {
    // 使用浏览器的 API 更新页面标题
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
//同时使用多个
function FriendStatusWithCounter(props) {
  const [count, setCount] = useState(0);
  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  const [isOnline, setIsOnline] = useState(null);
  useEffect(() => {
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }
  // ...

当需要清除某一个副作用时,副作用函数还可以通过返回一个函数来指定如何“清除”副作用。

使用effect hook的好处在于,可以将相关的逻辑分类集中绑定在一起,而不是像class里那样要拆分开,而且所有代码都挤在一个周期函数里面。

effect hook可以进行一些优化:我们可以在后面额外添加一个参数,用于判断其是否发生了变化,只有在变化时才会重新渲染执行。比如这样:

useEffect(() => {
  document.title = `You clicked ${count} times`;
}, [count]); // 仅在 count 更改时更新

注意:如果你要使用此优化方式,请确保数组中包含了所有外部作用域中会随时间变化并且在 effect 中使用的变量,否则你的代码会引用到先前渲染中的旧变量。

如果想执行只运行一次的 effect(仅在组件挂载和卸载时执行),可以传递一个空数组([])作为第二个参数。这就告诉 React 你的 effect 不依赖于 props 或 state 中的任何值,所以它永远都不需要重复执行。这并不属于特殊情况 —— 它依然遵循依赖数组的工作方式。

4.Hook使用规则

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

  • 只能在函数最外层调用 Hook。不要在循环、条件判断或者子函数中调用。
  • 只能在 React 的函数组件中调用 Hook。不要在其他 JavaScript 函数中调用。(还有一个地方可以调用 Hook —— 就是自定义的 Hook 中,我们稍后会学习到。)

在使用Hook的时候我们需要遵循这些规则来避免程序可能出现bug,我们只能在函数组件里面使用hook,且如果需要有条件判断等操作,可以将其写在hook里面,而不是在这些操作中调用。

遵守这些规则的目的在于避免程序出现不必要的错误,React会记住每次hook的调用顺序,只要hook的调用顺序与多次渲染前的保持一致,React就能正确将state和其对应的hook关联起来。

5.自定义Hook

有时候我们会想要在组件之间重用一些状态逻辑。目前为止,有两种主流方案来解决这个问题:高阶组件和 render props。自定义 Hook 可以让你在不增加组件的情况下达到同样的目的。

import React, { useState, useEffect } from 'react';

function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);

  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }

  useEffect(() => {
    ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
    };
  });

  return isOnline;
}

function FriendStatus(props) {
  const isOnline = useFriendStatus(props.friend.id);

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}

function FriendListItem(props) {
  const isOnline = useFriendStatus(props.friend.id);

  return (
    <li style={{ color: isOnline ? 'green' : 'black' }}>
      {props.friend.name}
    </li>
  );
}

我们可以将组件之间复用的部分提取出来放到自定义的hook里面,重复调用这个自定义的hook来实现复用。

自定义 Hook 更像是一种约定而不是功能。如果函数的名字以 “use” 开头并调用其他 Hook,我们就说这是一个自定义 Hook。 useSomething 的命名约定可以让我们的 linter 插件在使用 Hook 的代码中找到 bug。

我们自定义的hook必须以use开头,在两个组件中使用相同的hook不会共享state,每次调用hook都会获取独立的state,他们之间是完全独立的。

我们可以在hook之间传递信息:

const friendList = [
  { id: 1, name: 'Phoebe' },
  { id: 2, name: 'Rachel' },
  { id: 3, name: 'Ross' },
];

function ChatRecipientPicker() {
  const [recipientID, setRecipientID] = useState(1);
  const isRecipientOnline = useFriendStatus(recipientID);

  return (
    <>
      <Circle color={isRecipientOnline ? 'green' : 'red'} />
      <select
        value={recipientID}
        onChange={e => setRecipientID(Number(e.target.value))}
      >
        {friendList.map(friend => (
          <option key={friend.id} value={friend.id}>
            {friend.name}
          </option>
        ))}
      </select>
    </>
  );
}

我们通过传递参数的方式,在点击后state的值发生变化,页面重新渲染,hook里的方法也会重新执行,通过这个例子我们还能学到,不需要动态检测的变量我们可以写在外面而不是state里,类似于全局变量的方式进行调用。

6.一些补充

useState的函数式更新useState

当数据操作变得复杂时,可以选择使用这种方式处理。

function Counter({initialCount}) {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}
      <button onClick={() => setCount(initialCount)}>Reset</button>
      <button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
      <button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
    </>
  );
}

setState(prevState => {
  // 也可以使用 Object.assign
  return {...prevState, ...updatedValues};
});

链接里面还有一些其他的api可以参考使用。

7.总结

React Hook为React增添了一些新的可用的特性,我们可以在代码中尝试使用它来优化相关逻辑,之前在暑假项目实训的时候,用到了一种页面跳转的相关组件,其中的函数就只能写在函数组件里面,hook在这里就可以丰富函数组件里的相关功能。


  1. 我们之前可能已经在 React 组件中执行过数据获取、订阅或者手动修改过 DOM。我们统一把这些操作称为“副作用”,或者简称为“作用”。 ??

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 20:32:10  更:2022-10-08 20:34:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 19:23:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码