0


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。

function Todos() {
  const [todos, dispatch] = useReducer(todosReducer);
  // ...
标签: react.js 学习 前端

本文转载自: https://blog.csdn.net/wanghaoyingand/article/details/123206908
版权归原作者 接着奏乐接着舞。 所有, 如有侵权,请联系我们删除。

“react Hook学习笔记”的评论:

还没有评论