目次
react-hooks によって解決される問題
クラスと比較したフックの利点 (比較)
1. 記述方法がより簡潔になります
2. ビジネス コードはより集約されています
3. 便利なロジックの再利用
#フックの一般的な API の使用法
1、useState
useMemo および useCallback は主に、コンポーネントの更新数を減らし、コンポーネントのパフォーマンスを最適化するために使用されます。
4、useRef
5、useReducer
6、useContext
7、useLayoutEffect
ホームページ ウェブフロントエンド フロントエンドQ&A 反応フックとクラスの違いは何ですか?

反応フックとクラスの違いは何ですか?

Mar 22, 2022 pm 12:12 PM
class react hook

相違点: 1. フックはクラスよりも簡潔に記述されます; 2. フックのビジネス コードはクラスよりも集約されています; 3. クラス コンポーネントのロジックの再利用では通常、レンダリング プロパティと HOC が使用されますが、反応フックは使用を提供しますロジックを再利用するためのカスタム フック。

反応フックとクラスの違いは何ですか?

このチュートリアルの動作環境: Windows7 システム、react17.0.1 バージョン、Dell G3 コンピューター。

反応フックとクラスコンポーネントの違いは何ですか?反応フックとクラスコンポーネントを比較し、それらの違いについて話しましょう。

react-hooks によって解決される問題

  • 関数コンポーネントは独自の状態を持つことができません。フックが登場する前は、関数コンポーネントはステートレスであり、親コンポーネントの状態は props を通じて取得されていましたが、フックでは関数コンポーネントの内部状態を維持するための useState が提供されます。

  • コンポーネントのライフサイクルは、関数コンポーネントでは監視できません。 useEffect は複数のライフサイクル関数を集約します。

  • クラス コンポーネントのライフ サイクルはより複雑です (バージョン 15 からバージョン 16 への変更は大きくなります)。

  • クラス コンポーネント ロジックは再利用が困難です (HOC、レンダリング プロップ)。

クラスと比較したフックの利点 (比較)

1. 記述方法がより簡潔になります

私たちは以下を使用します最も単純なカウンター 例:

クラスコンポーネント

class ExampleOfClass extends Component {
  constructor(props) {
    super(props)
    this.state = {
      count: 1
    }
  }
  handleClick = () => {
    let { count } = this.state
    this.setState({
      count: count+1
    })
  }
  render() {
    const { count } = this.state
    return (
      <div>
        <p>you click { count }</p>
        <button onClick={this.handleClick}>点击</button>
      </div>
    )
  }
}
ログイン後にコピー

フック

function ExampleOfHooks() {
    const [count, setCount] = useState(0)
    const handleClick = () => {
        setCount(count + 1)
    }
    return (
      <div>
        <p>you click { count }</p>
        <button onClick={handleClick}>点击</button>
      </div>
    )
}
ログイン後にコピー

フックを使用したコードは次のとおりであることがわかります。クラスコンポーネントコードと比較して、より簡潔で明確です。

2. ビジネス コードはより集約されています

クラス コンポーネントを使用する場合、関数が 2 つのライフ サイクル関数に含まれることがよくあります。これらを別々に記述すると、場合によっては問題が発生する可能性があります。問題は忘れてください。例:

let timer = null
componentDidMount() {
    timer = setInterval(() => {
        // ...
    }, 1000)
}
// ...
componentWillUnmount() {
    if (timer) clearInterval(timer)
}
ログイン後にコピー

タイマーの追加とタイマーのクリアは 2 つの異なるライフサイクル関数に含まれるため、間に他の多くのビジネス コードが存在する可能性があるため、コンポーネントが次の場合にタイマーのクリアを忘れる可能性があります。クリアタイマー機能を追加しないと、メモリリークや継続的なネットワークリクエストなどの問題が発生する可能性があります。

しかし、フックを使用すると、コードがより集中化され、管理しやすくなり、忘れにくくなります:

useEffect(() => {
    let timer = setInterval(() => {
        // ...
    }, 1000)
    return () => {
        if (timer) clearInterval(timer)
    }
}, [//...])
ログイン後にコピー

3. 便利なロジックの再利用

クラス コンポーネントのロジック再利用では、通常、レンダー プロパティと HOC が使用されます。 React フックは、ロジックを再利用するためのカスタム フックを提供します。

以下では、例としてページ上のマウス位置を取得するロジックの再利用を取り上げています。

クラス コンポーネントのレンダー プロパティ メソッドの再利用

import React, { Component } from &#39;react&#39;

class MousePosition extends Component {
  constructor(props) {
    super(props)
    this.state = {
      x: 0,
      y: 0
    }
  }

  handleMouseMove = (e) => {
    const { clientX, clientY } = e
    this.setState({
      x: clientX,
      y: clientY
    })
  }

  componentDidMount() {
    document.addEventListener(&#39;mousemove&#39;, this.handleMouseMove)
  }

  componentWillUnmount() {
    document.removeEventListener(&#39;mousemove&#39;, this.handleMouseMove)
  }

  render() {
    const { children } = this.props
    const { x, y } = this.state
    return(
      <div>
        {
          children({x, y})
        }
      </div>
    )
  }

}

// 使用
class Index extends Component {
  constructor(props) {
    super(props)
  }

  render() {
    return (
      <MousePosition>
        {
          ({x, y}) => {
            return (
              <div>
                <p>x:{x}, y: {y}</p>
              </div>
            )
          }
        }
      </MousePosition>
    )
  }
}

export default Index
ログイン後にコピー

カスタム フック メソッドの再利用

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

function usePosition() {
  const [x, setX] = useState(0)
  const [y, setY] = useState(0)

  const handleMouseMove = (e) => {
    const { clientX, clientY } = e
    setX(clientX)
    setY(clientY)
  } 

  useEffect(() => {
    document.addEventListener(&#39;mousemove&#39;, handleMouseMove)
    return () => {
      document.removeEventListener(&#39;mousemove&#39;, handleMouseMove)
    }
  })
  return [
    {x, y}
  ]
}

// 使用
function Index() {
  const [position] = usePosition()
  return(
    <div>
      <p>x:{position.x},y:{position.y}</p>
    </div>
  )
}

export default Index
ログイン後にコピー

フックを使用すると、ロジックの再利用がより便利になり、使用するとロジックがより明確になることが明らかです。

#フックの一般的な API の使用法

1、useState

#Syntax

const [value, setValue] = useState(0)

この構文は ES6 配列構造です。配列の最初の値は宣言された状態で、2 番目の値は状態変化機能。

各フレームは独立した状態を持つ

私の個人的な理解では、各フレームの独立した状態はクロージャー メソッドを使用して実現されます。
function Example() {
  const [val, setVal] = useState(0)
  const timeoutFn = () => {
      setTimeout(() => {
        // 取得的值是点击按钮的状态,不是最新的状态
          console.log(val)
      }, 1000)
  }
  return (
      <>
          <p>{val}</p>
          <button onClick={()=>setVal(val+1)}>+</button>
          <button onClick={timeoutFn}>alertNumber</button>
      </>
  )
}
ログイン後にコピー

コンポーネントのステータスまたはプロパティが更新されると、関数コンポーネントはレンダリングのために再呼び出されます。各レンダリングは独立しており、独自の独立したプロパティと状態を持ち、他のレンダリングには影響しません。

2. useEffect

Syntax

useEffect(() => {
    //handler function...
    
    return () => {
        // clean side effect
    }
}, [//dep...])
ログイン後にコピー
useEffect は、依存関係が変更されたときにコールバック関数と依存関係を受け取ります。内部のコールバック関数が実行されます。 useEffect は、クラス コンポーネント DidMount、didUpdate、および willUnmount のライフサイクル関数に似ています。

    useEffect は非同期であり、コンポーネントがレンダリングされるまで実行されません
  • useEffect のコールバック関数は、副作用をクリアするか、返さない処理関数のみを返すことができます。
  • useEffect によって渡された依存関係が空の配列の場合、useEffect 内の関数は1 回実行
3. useMemo、useCallback

useMemo および useCallback は主に、コンポーネントの更新数を減らし、コンポーネントのパフォーマンスを最適化するために使用されます。

    useMemo はコールバック関数と依存関係を受け取り、コールバック関数は依存関係が変更された場合にのみ再実行されます。
  • useCallback は、コールバック関数と依存関係を受け取り、コールバック関数の記憶されたバージョンを返します。記憶されたバージョンは、依存関係が変更された場合にのみ再記憶されます。
構文

const memoDate = useMemo(() => data, [//dep...])
const memoCb = useCallback(() => {//...}, [//dep...])
ログイン後にコピー
コンポーネントのパフォーマンスを最適化するときは、通常、クラス コンポーネントに React.PureComponent を使用します。PureComponent は shouldUpdate で比較を実行します。更新が必要かどうか; 関数コンポーネントには通常 React.memo を使用します。ただし、react フックを使用すると、各レンダリング更新が独立している (新しい状態が生成される) ため、React.memo を使用した場合でも、再レンダリングが行われます。

比如下面这种场景,改变子组件的name值后由于父组件更新后每次都会生成新值(addAge函数会改变),所以子组件也会重新渲染。

function Parent() {
  const [name, setName] = useState(&#39;cc&#39;)
  const [age, setAge] = useState(22)

  const addAge = () => {
    setAge(age + 1)
  }

  return (
    <>
      <p>父组件</p>
      <input value={name} onChange={(e) => setName(e.target.value)} />
      <p>age: {age}</p>
      <p>-------------------------</p>
      <Child addAge={addAge} />
    </>
  )
}

const Child = memo((props) => {
  const { addAge } = props
  console.log(&#39;child component update&#39;)
  return (
    <>
      <p>子组件</p>
      <button onClick={addAge}>click</button>
    </>
  )
})
ログイン後にコピー

使用useCallback优化

function Parent() {
  const [name, setName] = useState(&#39;cc&#39;)
  const [age, setAge] = useState(22)

  const addAge = useCallback(() => {
    setAge(age + 1)
  }, [age])

  return (
    <>
      <p>父组件</p>
      <input value={name} onChange={(e) => setName(e.target.value)} />
      <p>age: {age}</p>
      <p>-------------------------</p>
      <Child addAge={addAge} />
    </>
  )
}

const Child = memo((props) => {
  const { addAge } = props
  console.log(&#39;child component update&#39;)
  return (
    <>
      <p>子组件</p>
      <button onClick={addAge}>click</button>
    </>
  )
})
ログイン後にコピー

只有useCallback的依赖性发生变化时,才会重新生成memorize函数。所以当改变name的状态是addAge不会变化。

4、useRef

useRef类似于react.createRef。

const node = useRef(initRef)
ログイン後にコピー

useRef 返回一个可变的 ref 对象,其 current 属性被初始化为传入的参数(initRef)

作用在DOM上

const node = useRef(null)
<input ref={node} />
ログイン後にコピー

这样可以通过node.current属性访问到该DOM元素。

需要注意的是useRef创建的对象在组件的整个生命周期内保持不变,也就是说每次重新渲染函数组件时,返回的ref 对象都是同一个(使用 React.createRef ,每次重新渲染组件都会重新创建 ref)。

5、useReducer

useReducer类似于redux中的reducer。

语法

const [state, dispatch] = useReducer(reducer, initstate)
ログイン後にコピー

useReducer传入一个计算函数和初始化state,类似于redux。通过返回的state我们可以访问状态,通过dispatch可以对状态作修改。

const initstate = 0;
function reducer(state, action) {
  switch (action.type) {
    case &#39;increment&#39;:
      return {number: state.number + 1};
    case &#39;decrement&#39;:
      return {number: state.number - 1};
    default:
      throw new Error();
  }
}
function Counter(){
    const [state, dispatch] = useReducer(reducer, initstate);
    return (
        <>
          Count: {state.number}
          <button onClick={() => dispatch({type: &#39;increment&#39;})}>+</button>
          <button onClick={() => dispatch({type: &#39;decrement&#39;})}>-</button>
        </>
    )
}
ログイン後にコピー

6、useContext

通过useContext我们可以更加方便的获取上层组件提供的context。

父组件

import React, { createContext, Children } from &#39;react&#39;
import Child from &#39;./child&#39;

export const MyContext = createContext()

export default function Parent() {

  return (
    <div>
      <p>Parent</p>
      <MyContext.Provider value={{name: &#39;cc&#39;, age: 21}}>
        <Child />
      </MyContext.Provider>
    </div>
  )
}
ログイン後にコピー

子组件

import React, { useContext } from &#39;react&#39;
import { MyContext } from &#39;./parent&#39;

export default function Parent() {
  const data = useContext(MyContext) // 获取父组件提供的context
  console.log(data)
  return (
    <div>
      <p>Child</p>
    </div>
  )
}
ログイン後にコピー

使用步骤

  • 父组件创建并导出context:export const MyContext = createContext()
  • 父组件使用providervalue提供值:<MyContext.provide value={{name: &#39;cc&#39;, age: 22}} />
  • 子组件导入父组件的context:import { MyContext } from &#39;./parent&#39;
  • 获取父组件提供的值:const data = useContext(MyContext)

不过在多数情况下我们都不建议使用context,因为会增加组件的耦合性。

7、useLayoutEffect

useEffect 在全部渲染完毕后才会执行;useLayoutEffect 会在 浏览器 layout之后,painting之前执行,并且会柱塞DOM;可以使用它来读取 DOM 布局并同步触发重渲染。

export default function LayoutEffect() {
  const [color, setColor] = useState(&#39;red&#39;)
  useLayoutEffect(() => {
      alert(color) // 会阻塞DOM的渲染
  });
  useEffect(() => {
      alert(color) // 不会阻塞
  })
  return (
      <>
        <div id="myDiv" style={{ background: color }}>颜色</div>
        <button onClick={() => setColor(&#39;red&#39;)}>红</button>
        <button onClick={() => setColor(&#39;yellow&#39;)}>黄</button>
      </>
  )
}
ログイン後にコピー

上面的例子中useLayoutEffect会在painting之前执行,useEffect在painting之后执行。

hooks让函数组件拥有了内部状态、生命周期,使用hooks让代码更加的简介,自定义hooks方便了对逻辑的复用,并且摆脱了class组件的this问题;但是在使用hooks时会产生一些闭包问题,需要仔细使用。

【相关推荐:Redis视频教程

以上が反応フックとクラスの違いは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Python でクラスとメソッドを使用する方法 Python でクラスとメソッドを使用する方法 Apr 21, 2023 pm 02:28 PM

クラスとメソッドの概念とインスタンス クラス (Class): 同じプロパティとメソッドを持つオブジェクトのコレクションを記述するために使用されます。コレクション内のすべてのオブジェクトに共通のプロパティとメソッドを定義します。オブジェクトはクラスのインスタンスです。メソッド: クラスで定義された関数。クラス構築メソッド __init__(): クラスには init() という名前の特別なメソッド (構築メソッド) があり、クラスがインスタンス化されるときに自動的に呼び出されます。インスタンス変数: クラスの宣言において、属性を変数で表現したものをインスタンス変数と呼びます。インスタンス変数とは、self で修飾された変数です。インスタンス化: クラスのインスタンス、クラスの特定のオブジェクトを作成します。継承: つまり、派生クラス (派生クラス) は基本クラス (ベースクラス) を継承します。

Pythonにおけるクラスとは何を意味するのでしょうか? Pythonにおけるクラスとは何を意味するのでしょうか? May 21, 2019 pm 05:10 PM

クラスとはPythonでクラスを定義するためのキーワードです クラスの定義方法:classの後ろにスペースを入れてからクラス名を追加します; クラス名のルール:最初の文字を大文字にします 複数の単語がある場合はキャメルケースを使用してください[class Dog()] などの名前付け。

jQueryを使用して要素のクラス名を置換する jQueryを使用して要素のクラス名を置換する Feb 24, 2024 pm 11:03 PM

jQuery は、Web 開発で広く使用されている古典的な JavaScript ライブラリで、イベントの処理、DOM 要素の操作、Web ページ上でのアニメーションの実行などの操作を簡素化します。 jQueryを使っていると要素のクラス名を置き換える場面がよくありますが、この記事ではその実践的な方法と具体的なコード例を紹介します。 1.removeClass() メソッドと addClass() メソッドを使用する jQuery には、削除用の RemoveClass() メソッドが用意されています。

PHP クラスの使用法の詳細な説明: コードをより明確で読みやすくします。 PHP クラスの使用法の詳細な説明: コードをより明確で読みやすくします。 Mar 10, 2024 pm 12:03 PM

PHP コードを記述するとき、クラスを使用するのは非常に一般的な方法です。クラスを使用すると、関連する関数とデータを 1 つのユニットにカプセル化できるため、コードがより明確になり、読みやすく、保守しやすくなります。この記事では、PHPClass の使用法を詳しく紹介し、クラスを適用して実際のプロジェクトでコードを最適化する方法を読者がよりよく理解できるように、具体的なコード例を示します。 1. クラスの作成と使用 PHP では、キーワード class を使用してクラスを定義し、クラス内のプロパティとメソッドを定義できます。

Vue エラー: v-bind を使用してクラスとスタイルを正しくバインドできません。解決方法は? Vue エラー: v-bind を使用してクラスとスタイルを正しくバインドできません。解決方法は? Aug 26, 2023 pm 10:58 PM

Vue エラー: v-bind を使用してクラスとスタイルを正しくバインドできません。解決方法は? Vue 開発では、v-bind 命令を使用してクラスとスタイルを動的にバインドすることがよくありますが、v-bind を正しく使用してクラスとスタイルをバインドできないなどの問題が発生することがあります。この記事では、この問題の原因と解決策を説明します。まず、v-bind ディレクティブを理解しましょう。 v-bind は V をバインドするために使用されます

SpringBoot がカスタム クラスローダーを通じてクラス ファイルを暗号化および保護する方法 SpringBoot がカスタム クラスローダーを通じてクラス ファイルを暗号化および保護する方法 May 11, 2023 pm 09:07 PM

背景 最近、jd-gui などの逆コンパイル ツールによってエンジニアリング コードが簡単に復元されないようにするために、企業のフレームワークでは主要なビジネス コードが暗号化されていますが、関連する難読化スキームの構成と使用は比較的複雑であり、多くの問題が発生しています。 springboot プロジェクトなので、クラス ファイルが暗号化されて渡されます。カスタム クラスローダが復号化されてロードされます。このソリューションは絶対に安全というわけではありません。逆コンパイルの難易度が上がるだけです。紳士は阻止できますが、悪党は阻止できません。全体的な暗号化保護のフローチャートが示されています。 Maven プラグインの暗号化では、カスタム Maven プラグインを使用してコンパイルします。指定されたクラス ファイルが暗号化され、暗号化されたクラス ファイルが指定されたパスにコピーされます。ここでは、resource/corecla に保存されます。

jqueryで要素にクラスがあるかどうかを確認する方法 jqueryで要素にクラスがあるかどうかを確認する方法 Mar 21, 2023 am 10:47 AM

jquery が要素にクラスがあるかどうかを判断する方法: 1. 「hasClass('classname')」メソッドを通じて要素に特定のクラスがあるかどうかを判断します; 2. 「is('.classname」を通じて要素に特定のクラスがあるかどうかを判断します。 ')" 方法。

「[Vue warn]: v-bind:class/ :class」エラーを解決する方法 「[Vue warn]: v-bind:class/ :class」エラーを解決する方法 Aug 26, 2023 am 08:17 AM

「[Vuewarn]:v-bind:class/:class」エラーを解決する方法 Vue を使用した開発プロセス中に、いくつかのエラー プロンプトに遭遇することがよくあります。一般的なエラーの 1 つは、「[Vuewarn]:v-bind:class」です。 「/:クラス」エラー。このエラー メッセージは通常、v-bind:class または :class 属性を使用するときに表示され、Vue が設定したクラス値を正しく解析できないことを示します。そうすると、

See all articles