zoukankan      html  css  js  c++  java
  • React Hook(自定义 Hook)

    前沿

    想写下react hooks ,一些基本资料,当然也可以看官网,我只是整理下

     react hooks 的官方基本介绍可以看 React 的文档:https://reactjs.org/docs/hooks-intro.html

    一、State Hook

    以一个简单的计数器举例,使用 useState 这个 Hook:

    import { useState } from 'react';
    function Example() {
      // Declare a new state variable, which we'll call "count"
      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 在 re-render 之前会保留这个 state。useState 返回两个内容:

    • 当前的 state 值
    • 一个允许更新 state 值的 function

    可以从事件处理程序或者其他位置调用返回的 function,和类中的 this.setState 比较累色,只不过不会将新的 state 和旧的 state 合并在一起。(React 给过一个使用 useState 和 this.state 的比较的示例https://reactjs.org/docs/hooks-state.html

    useState 的唯一参数是初始状态,在上面的例子中,初始 state 是 0,因为计数器从 0 开始。请注意,和 this.state 不同的是,这里的 state 不一定是对象,可以是随便需要的形式。而初始状态参数仅仅在第一次渲染的时候使用。

    1、声明多个 state 变量

    可以在单个组件中多次使用 state Hook:

    function ExampleWithManyStates() {
      // Declare multiple state variables!
      const [age, setAge] = useState(42);
      const [fruit, setFruit] = useState('banana');
      const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
      // ...
    }

    数组结构语法允许给 useState 的声明的 state 变量赋予不同的名称,这些名称并不是 useState API 的一部分。相反,React 假定如果多次调用 useState,则在每次渲染期间,以相同的顺序执行。

    2、什么是 Hook

    Hook 是允许从功能组件 挂钩 React 的 state 和生命周期方法等功能。Hook 在类的内部不起作用——允许在没有类的情况下使用 React。(React 不建议全部重写组件,只是建议如果感兴趣 Hook,可以在新的组件中使用)

    React 提供了一些像 useState 这样的内置 Hook,还可以创建自己的 Hook 以便于重用不同组件之间的状态行为。

    二、Effect Hook

    我们已经可以在 React 组件中进行数据请求、subscriptions 或者是手动更改 DOM。

    这些操作都是称为 side effects,也就是副作用。因为它们会影响其他组件,并且在渲染过程中没有办法完成。

    useEffect 增加了从功能组件执行副作用的功能。它与 React 类的 componentDidMountcomponentDidUpdate 和 componentWillUnmount 具有相同的效果,但是统一成了一个 API。可以在 Using the Effect Hool 文档中查找关于更多 useEffect 的内容。

    例如,下面的组件在 React 更新 DOM 后设置文档标题:

    import { useState, useEffect } from 'react';
    function Example() {
      const [count, setCount] = useState(0);
      // Similar to componentDidMount and componentDidUpdate:
      useEffect(() => {
        // Update the document title using the browser 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 的更改后运行 effect 副作用方法。因为 副作用方法 是在组件中声明的,因此可以访问 props 和 state。

    默认情况下, React 在每次渲染后执行 effect 方法 —— 包括第一次渲染。想查看和生命周期方法的比较,也可以在 Using the Effect Hool 文档中找到。

    同时 effect 副作用方法可以通过返回函数指定如何 “清理” 它们。例如,下面组件使用效果来订阅好友的在线 state,并通过取消订阅来实现清理的目的:

    import { 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';
    }

    在这个示例中,组件卸载或者是由于后面的 re-render 而重新执行副作用方法之前,React 会取消订阅 ChatAPI。当然,如果 props 传过来的 id 是没有变化的,也可以通过某种方式来跳过订阅和取消订阅的行为:https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects

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

    Hooks 允许通过哪些部分相关(比如添加和删除订阅)来组织组件中的副作用,而不是基于生命周期方法进行强制拆分。

    三、 Hooks 的规则

    Hooks 是 JavaScript 方法, 但它们强加了两个额外的规则:

    • 只能在顶层调用 Hooks,不能再循环、条件或者是嵌套方法中调用 Hooks。
    • 仅在 React 功能组件中使用 Hooks。不能再常规的 JavaScript 方法中调用 Hook。

    React 提供了一个 linter 插件 来自动执行这些规则。虽然这些规则可能会让开发者比较首先,但是对于 Hooks 的良好运行至关重要。

    四、构建自己的 Hook

    有时,可能会希望在组件之间重用一些 state 的逻辑,一般之前的做法都是通过高阶组件或者是 render props 来解决。自定义 Hook 能够做到这种需求,而不需要向 tree 中增加更多组件。

    前面虽然介绍了 useState 和 useEffect 来订阅朋友的在线状态,如果还希望在另一个组件中重用订阅逻辑,首先需要将这个逻辑提取到一个名为 useFriendStatus 的自定义 Hook 中:

    import { 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 ,返回的是好友是否在线。

    而现在可以在两个组件中直接使用这个 Hook:

    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 是重用有 state 逻辑的一种方式,而不是重用 state 本身。事实上,每次调用 Hook 都会有个完全隔离的状态。因此可以在一个组件中使用相同的自定义 Hook 两次。

    自定义 Hook 更像是一种约定,而不是一种功能。如果函数的名字以 use 开头,并且调用了其他的 Hook,则就称其为一个自定义 Hook。useSomething 命名约定是为了 linter 插件在代码中查找错误。

    五、其他的 Hooks

    除了上面的 useState 和 useEffect 之外,还有一些其他不太常用的 Hook 也可能很有用。比如 useContext 允许订阅 React 上下文,不去引入嵌套。

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

    而 useReducer 允许使用 reducer 管理复杂的组件 state:

    
    
    function Todos() {
      const [todos, dispatch] = useReducer(todosReducer);
      // ...
    
    
    就简答的介绍下HOOK吧,在数据请求的时候还是用到很多的
  • 相关阅读:
    并查集 [Total Eclipse]
    2020 Multi-University Training Contest 2 [The Oculus]
    2020牛客暑期多校训练营(第三场)G Operating on a Graph
    杭电多校第一场 [Fibonacci Sum]
    Codeforces Round #658 (Div. 2) E. Mastermind
    二次剩余
    SpringBlade 后端项目 部署 2.0-boot
    SpringBlade 前端项目 部署 Saber
    前端 天气插件
    SpringBlade 打包
  • 原文地址:https://www.cnblogs.com/yf-html/p/14977572.html
Copyright © 2011-2022 走看看