温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

React的Hook是什么

发布时间:2022-03-16 13:34:04 来源:亿速云 阅读:155 作者:小新 栏目:开发技术

这篇文章主要介绍了React的Hook是什么,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。


      State Hook

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

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

      在这里,useState 就是一个 Hook (等下我们会讲到这是什么意思)。通过在函数组件里调用它来给组件添加一些内部 state。React 会在重复渲染时保留这个 stateuseState 会返回一对值:当前状态一个让你更新它的函数,你可以在事件处理函数中或其他一些地方调用这个函数。它类似 class 组件的 this.setState,但是它不会把新的 state 和旧的 state 进行合并。(我们会在使用 State Hook 里展示一个对比 useState 和 this.state 的例子)。

      useState 唯一的参数就是初始 state。在上面的例子中,我们的计数器是从零开始的,所以初始 state 就是 0。值得注意的是,不同于 this.state,这里的 state 不一定要是一个对象 &mdash;&mdash; 如果你有需要,它也可以是。这个初始 state 参数只有在第一次渲染时会被用到。

      声明多个 state 变量

      你可以在一个组件中多次使用 State Hook:

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

      数组解构的语法让我们在调用 useState 时可以给 state 变量取不同的名字。当然,这些名字并不是 useState API 的一部分。React 假设当你多次调用 useState 的时候,你能保证每次渲染时它们的调用顺序是不变的。后面我们会再次解释它是如何工作的以及在什么场景下使用。

      那么,什么是 Hook?

      Hook 是一些可以让你在函数组件里 " 钩入" React state 及生命周期等特性的函数。Hook 不能在 class 组件中使用 &mdash;&mdash; 这使得你不使用 class 也能使用 React。(我们不推荐把你已有的组件全部重写,但是你可以在新组件里开始使用 Hook。)

      React 内置了一些像 useState 这样的 Hook。你也可以创建你自己的 Hook 来复用不同组件之间的状态逻辑。我们会先介绍这些内置的 Hook。

      Effect Hook

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

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

      例如,下面这个组件在 React 更新 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 会在每次渲染后调用副作用函数 &mdash;&mdash; 包括第一次渲染的时候。

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

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

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

      Hook 使用规则

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

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

      • 只能在 React 的函数组件中调用 Hook。不要在其他 JavaScript 函数中调用。(还有一个地方可以调用 Hook &mdash;&mdash; 就是自定义的 Hook 中,我们稍后会学习到。)

      自定义 Hook

      有时候我们会想要在组件之间重用一些状态逻辑。目前为止,有两种主流方案来解决这个问题:高阶组件和 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>
        );
      }

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

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

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

      其他 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的Hook是什么”这篇文章对大家有帮助,同时也希望大家多多支持亿速云,关注亿速云行业资讯频道,更多相关知识等着你来学习!

      向AI问一下细节

      免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

      AI