react Hook学习笔记

简介: react Hook学习笔记

前言:


react中有个词叫做“副作用”,它的意思是:在 React 组件中执行过数据获取、订阅或者手动修改过 DOM。我们统一把这些操作称为“副作用”,或者简称为“作用”。

1.是什么


ps:简单理解为一个新的用来代替或者说弥补class的不足,如this问题,嵌套地狱,可维护性等;而且它很方便的为我们提供很多强大的API,可以更加便捷的使用react开发。

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

Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。Hook 不能在 class 组件中使用 —— 这使得你不使用 class 也能使用 React。

这个例子用来显示一个计数器。当你点击按钮,计数器的值就会增加:

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>
  );
}

2.特点:


2.1 完全可选的

你无需重写任何已有代码就可以在一些组件中尝试 Hook。但是如果你不想,你不必现在就去学习或使用 Hook。

2.2 渐进增强

100% 向后兼容的。 Hook 不包含任何破坏性改动。

2.3 现在可用

Hook 已发布于 v16.8.0。

2.4 小结:

Hook 为已知的 React 概念提供了更直接的 API:props, state,context,refs 以及生命周期。Hook 还提供了一种更强大的方式来组合他们。


3.工作常用的Hook api

3.1 是怎么定义数据的?State Hook

ps:这里用到了数组解构

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

3.2 是怎么操作数据或者DOM的?Effect Hook

useEffect 就是一个 Effect Hook,给函数组件增加了操作副作用的能力。它跟 class 组件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount 具有相同的用途,只不过被合并成了一个 API。(我们会在使用 Effect Hook 里展示对比 useEffect 和这些方法的例子。)

下面这个组件在 React 更新 DOM 后会设置一个页面标题:注意它的执行周期(更新 DOM 后

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>
  );
}

当你调用 useEffect 时,就是在告诉 React 在完成对 DOM 的更改后运行你的“副作用”函数。由于副作用函数是在组件内声明的,所以它们可以访问到组件的 props 和 state。默认情况下,React 会在每次渲染后调用副作用函数 —— 包括第一次渲染的时候。(我们会在使用 Effect Hook 中跟 class 组件的生命周期方法做更详细的对比。)

ps:简单理解为由于props/state之类的都在一个函数内,共享一个作用域,所以不用this

3.3 是怎么清除副作用的?

副作用函数还可以通过返回一个函数来指定如何“清除”副作用。例如,在下面的组件中使用副作用函数来订阅好友的在线状态,并通过取消订阅来进行清除操作:

import React, { useState, useEffect } from 'react';
function FriendStatus(props) {
  const [isOnline, setIsOnline] = useState(null);
  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }
  useEffect(() => {
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });
  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}

在这个示例中,React 会在组件销毁时取消对 ChatAPI 的订阅,然后在后续渲染时重新执行副作用函数。(如果传给 ChatAPI 的 props.friend.id 没有变化,你也可以告诉 React 跳过重新订阅。)

跟 useState 一样,你可以在组件中多次使用 useEffect :

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);
  }
  // ...

3.4小结:

通过使用 Hook,你可以把组件内相关的副作用组织在一起(例如创建订阅及取消订阅),而不要把它们拆分到不同的生命周期函数里。

4.Hook 使用规则


4.1 只能在函数最外层调用 Hook

不要在循环、条件判断或者子函数中调用。

4.2 只能在 React 的函数组件中调用 Hook。

不要在其他 JavaScript 函数中调用。(还有一个地方可以调用 Hook —— 就是自定义的 Hook 中)

5.自定义 Hook——组件间的数据传递


5.1 作用:

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

前面,我们介绍了一个叫 FriendStatus 的组件,它通过调用 useState 和 useEffect 的 Hook 来订阅一个好友的在线状态。假设我们想在另一个组件里重用这个订阅逻辑。

首先,我们把这个逻辑抽取到一个叫做 useFriendStatus 的自定义 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;
}

它将 friendID 作为参数,并返回该好友是否在线:

现在我们可以在两个组件中使用它:

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>
  );
}

5.2小结:

ps:简单理解为,我定义一个公共的函数,然后每个函数都可以调用这个函数

每个组件间的 state 是完全独立的。Hook 是一种复用状态逻辑的方式,它不复用 state 本身。事实上 Hook 的每次调用都有一个完全独立的 state —— 因此你可以在单个组件中多次调用同一个自定义 Hook。

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

你可以创建涵盖各种场景的自定义 Hook,如表单处理、动画、订阅声明、计时器,甚至可能还有更多我们没想到的场景。我们很期待看到 React 社区会出现什么样的自定义 Hook。

6.其他 Hook


除此之外,还有一些使用频率较低的但是很有用的 Hook。比如,useContext 让你不使用组件嵌套就可以订阅 React 的 Context。

function Example() {
  const locale = useContext(LocaleContext);
  const theme = useContext(ThemeContext);
  // ...
}

另外 useReducer 可以让你通过 reducer 来管理组件本地的复杂 state。

1. function Todos() {
2. const [todos, dispatch] = useReducer(todosReducer);
3. // ...
相关文章
|
1月前
|
前端开发 JavaScript
【边做边学】React Hooks (二)——useEffect Hook
【边做边学】React Hooks (二)——useEffect Hook
|
1月前
|
前端开发 JavaScript
React中useEffect Hook使用纠错
React中useEffect Hook使用纠错
23 0
|
1月前
|
前端开发
React学习笔记(一)
React学习笔记(一)
|
1月前
|
前端开发
React学习笔记
React学习笔记
|
1月前
|
自然语言处理 前端开发 JavaScript
说说你对 React Hook的闭包陷阱的理解,有哪些解决方案?
说说你对 React Hook的闭包陷阱的理解,有哪些解决方案?
65 0
|
1月前
|
前端开发 JavaScript
《Webpack5 核心原理与应用实践》学习笔记-> React全栈环境
《Webpack5 核心原理与应用实践》学习笔记-> React全栈环境
47 0
|
6月前
|
自然语言处理 前端开发 JavaScript
美丽的公主和它的27个React 自定义 Hook(四)
美丽的公主和它的27个React 自定义 Hook(四)
|
6月前
|
存储 前端开发 数据可视化
美丽的公主和它的27个React 自定义 Hook(三)
美丽的公主和它的27个React 自定义 Hook(三)
|
6月前
|
存储 JSON 前端开发
美丽的公主和它的27个React 自定义 Hook(二)
美丽的公主和它的27个React 自定义 Hook(二)
|
6月前
|
前端开发 JavaScript API
美丽的公主和它的27个React 自定义 Hook(一)
美丽的公主和它的27个React 自定义 Hook(一)