ホームページ >ウェブフロントエンド >jsチュートリアル >この記事では React Hooks について徹底的に理解します。

この記事では React Hooks について徹底的に理解します。

青灯夜游
青灯夜游転載
2022-03-21 11:31:552413ブラウズ

React のフックをご存知ですか?この記事では React Hooks について詳しく説明しますので、お役に立てれば幸いです。

この記事では React Hooks について徹底的に理解します。

序文

フックは、クラスを作成せずに状態やその他の React 機能を使用するために使用されます。それでは、フックとは正確には何ですか、なぜフックを使用する必要があるのか​​、React が提供する一般的なフックは何ですか、そしてフックをカスタマイズする方法は何でしょうか? 以下では、それらを 1 つずつ説明します。 [関連する推奨事項: Redis ビデオ チュートリアル ]

フックとは

フックはフックと訳されます。フックは、外部関数にフックする役割を担う関数コンポーネント内の関数です。

React はいくつかの共通フックを提供しており、React は関数に外部関数を導入するために使用されるカスタム フックもサポートしています。

外部関数をコンポーネントに導入する必要がある場合、React が提供するフックを使用するか、フックをカスタマイズできます。

例えば、コンポーネントに状態を管理する機能を導入する場合、useState関数を使用することができますが、useStateの使い方については、以下で詳しく紹介します。

フックを使用する理由

フックを使用する主な理由は 2 つあります:

  • ロジックの再利用を簡素化する;
  • 複雑なコンポーネントを理解しやすくする。

1. ロジックの再利用を簡素化する

フックが登場する前は、React は高次コンポーネントやレンダリング プロップなどの複雑な設計パターンを借用して実装する必要がありました。ロジックを再利用しますが、上位のコンポーネントは冗長なコンポーネント ノードを生成するため、デバッグがより複雑になります。

フックを使用すると、コンポーネント構造を変更せずに状態ロジックを再利用できます。カスタム フックの使用方法については、以下で詳しく紹介します。

2. 複雑なコンポーネントを理解しやすくする

クラス コンポーネントでは、同じビジネス ロジックのコードがコンポーネントのさまざまなライフ サイクル関数とフックに分散されています。同じビジネス ロジックのコードを集約してビジネス ロジックを明確に分離し、コードの理解と保守を容易にします。

4. 一般的に使用されるフック

1. useState

useState は、React 関数コンポーネントに状態を追加できるようにするフックです。

使用例は次のとおりです。

import React, { useState } from 'react';

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

上記のコードは、状態変数 count を初期値 0 で宣言し、setCount を呼び出して現在のカウントを更新します。

2. useEffect

useEffect を使用すると、関数コンポーネントで副作用を実行できます。

副作用とは、現在の実行結果とは何の関係もないコードのことを指します。一般的な副作用操作には、データの取得、サブスクリプションの設定、React コンポーネントの DOM の手動変更などがあります。

useEffect は 2 つのパラメーターを受け取ることができます。コードは次のとおりです。

useEffect(callback, dependencies)

最初のパラメーターは実行される関数コールバックで、2 番目のパラメーターはオプションの依存関係配列の依存関係です。

依存関係はオプションです。指定しない場合、コールバックは各関数コンポーネントが実行された後に実行されます。指定した場合、依存関係の値が変更された場合にのみ実行されます。

使用例は次のとおりです。

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 () => {
        // 可用于做清除,相当于 class 组件的 componentWillUnmount
    }

  }, [count]); // 指定依赖项为 count,在 count 更新时执行该副作用
  // ...

上記のコードは、useEffect を使用して、依存関係の数が更新されるとき、副作用関数が実行されるとき、および最後の実行結果が返されることによってクリアされるときに実装します。コールバック関数。

さらに、useEffect は副作用を実行するための 4 つのタイミングを提供します。

  • 各レンダリング後に実行: 2 番目の依存関係パラメーターは提供されません。たとえば、useEffect(() => {});
  • 最初のレンダリング後にのみ実行されます: 依存関係として空の配列を指定します。たとえば、 useEffect(() => {}, []);
  • 初回および依存関係の変更後に実行: 依存関係の配列を指定します。たとえば、useEffect(() => {}, [deps]);
  • コンポーネントがアンマウントされた後、execute: コールバック関数を返します。たとえば、 useEffect() => { return () => {} }, []) です。

3. useCallback

useCallback で定義されたコールバック関数は、依存関係が変更された場合にのみコールバック関数を再宣言するため、 コンポーネントが確実に複製されます。コールバック関数は作成されません。このコールバック関数を属性として受け取るコンポーネントは、 頻繁に再レンダリングする必要はありません。

使用例は次のとおりです。

const memoizedCallback = useCallback(() => {
  doSomething(a, b)
}, [a, b])

上記のコードは、依存関係 a と b が変更された場合にのみコールバック関数を再宣言します。

4. useMemo

useMemo で定義された作成関数は、依存関係が変更された場合にのみ再計算されるため、

コストのかかる計算が繰り返されることはありません と、この計算された値をプロパティとして受け取るコンポーネントは、 頻繁に再レンダリングする必要がなくなります。 使用例は次のとおりです。

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b])

上記のコードは、依存関係 a と b が変更された場合にのみ再計算されます。

5. useRef

useRef は、コンポーネントのライフサイクル全体にわたって持続する ref オブジェクトを返します。

彼には 2 つの用途があります:

  • 保存 DOM 节点的引用
  • 在多次渲染之间共享数据

保存 DOM 节点的引入使用示例如下:

function TextInputWithFocusButton() {
  const inputEl = useRef(null)
  const onButtonClick = () => {
    // `current` 指向已挂载到 DOM 上的文本输入元素
    inputEl.current.focus()
  }
  return (
    <>
      <input ref={inputEl} type=&#39;text&#39; />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  )
}

以上代码通过 useRef 创建了 ref 对象,保存了 DOM 节点的引用,可以对 ref.current 做 DOM 操作。

在多次渲染之间共享数据示例如下:

import React, { useState, useCallback, useRef } from &#39;react&#39;

export default function Timer() {
  // 定义 time state 用于保存计时的累积时间
  const [time, setTime] = useState(0)

  // 定义 timer 这样一个容器用于在跨组件渲染之间保存一个变量
  const timer = useRef(null)

  // 开始计时的事件处理函数
  const handleStart = useCallback(() => {
    // 使用 current 属性设置 ref 的值
    timer.current = window.setInterval(() => {
      setTime((time) => time + 1)
    }, 100)
  }, [])

  // 暂停计时的事件处理函数
  const handlePause = useCallback(() => {
    // 使用 clearInterval 来停止计时
    window.clearInterval(timer.current)
    timer.current = null
  }, [])

  return (
    <div>
      {time / 10} seconds.
      <br />
      <button onClick={handleStart}>Start</button>
      <button onClick={handlePause}>Pause</button>
    </div>
  )
}

以上代码通过 useRef 创建了一个变量名为 timer 的 ref 对象,该对象可以在跨组件渲染时调用,在开始计时时新建计时器,在暂停计时时清空计时器。

6. useContext

useContext 用于接收一个 context 对象并返回该 context 的值,可以实现跨层级的数据共享。

示例如下:

// 创建一个 context 对象
const MyContext = React.createContext(initialValue)
function App() {
  return (
    // 通过 Context.Provider 传递 context 的值
    <MyContext.Provider value=&#39;1&#39;>
      <Container />
    </MyContext.Provider>
  )
}

function Container() {
  return <Test />
}

function Test() {
  // 获取 Context 的值
  const theme = useContext(MyContext) // 1
  return <div></div>
}

以上代码通过 useContext 取得了 App 组件中定义的 Context,做到了跨层次组件的数据共享。

7. useReducer

useReducer 用来引入 Reducer 功能。

示例如下:

const [state, dispatch] = useReducer(reducer, initialState)

它接受 Reducer 函数和状态的初始值作为参数,返回一个数组。数组的第一个成员是状态的当前值,第二个成员是发送 action 的 dispatch 函数。

五、自定义 Hooks

通过自定义 Hooks,可以将组件逻辑提取到可重用的函数中。

1. 如何创建自定义 Hooks?

自定义 Hooks 就是函数,它有 2 个特征区分于普通函数:

  • 名称以 “use” 开头;
  • 函数内部调用其他的 Hook。

示例如下:

import { useState, useCallback } from &#39;react&#39;

function useCounter() {
  // 定义 count 这个 state 用于保存当前数值
  const [count, setCount] = useState(0)
  // 实现加 1 的操作
  const increment = useCallback(() => setCount(count + 1), [count])
  // 实现减 1 的操作
  const decrement = useCallback(() => setCount(count - 1), [count])
  // 重置计数器
  const reset = useCallback(() => setCount(0), [])

  // 将业务逻辑的操作 export 出去供调用者使用
  return { count, increment, decrement, reset }
}

// 组件1
function MyComponent1() {
  const { count, increment, decrement, reset } = useCounter()
}

// 组件2
function MyComponent2() {
  const { count, increment, decrement, reset } = useCounter()
}

以上代码通过自定义 Hooks useCounter,轻松的在 MyComponent1 组件和 MyComponent2 组件之间复用业务逻辑。

2. 自定义 Hooks 库 - react-use

React 官方提供了 react-use 库,其中封装了大量可直接使用的自定义 Hooks,帮助我们简化组件内部逻辑,提高代码可读性、可维护性。

其中我们常用的自定义 Hooks 有:

  • useLocation 和 useSearchParam:跟踪页面导航栏位置状态;
  • useScroll:跟踪 HTML 元素的滚动位置;
  • useScrolling:跟踪 HTML 元素是否正在滚动;
  • useAsync, useAsyncFn, and useAsyncRetry:解析一个 async 函数;
  • useTitle:设置页面的标题。

可至 react-use 官网学习使用。

六、小结

本文从 Hooks 究竟是什么,为什么要使用 Hooks,React 提供了哪些常用 Hooks,以及如何自定义 Hooks 4 个方面介绍了 React Hooks,相信大家对 React Hooks 已经有了更加深入的理解。

希望能对你有所帮助,感谢阅读~

更多编程相关知识,请访问:编程入门!!

以上がこの記事では React Hooks について徹底的に理解します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。