web-dev-qa-db-ja.com

ReactフックでcomponentWillMount()を使用するには?

Reactの公式ドキュメントでは、次のように言及しています-

Reactクラスのライフサイクルメソッドに精通している場合、useEffectフックはcomponentDidMount、componentDidUpdate、およびcomponentWillUnmountを組み合わせたものと考えることができます。

私の質問は-フックでcomponentWillMount() lifecyleメソッドをどのように使用できますか?

51
Abrar

フックでは既存のライフサイクルメソッド(componentDidMount、componentDidUpdate、componentWillUnmountなど)を使用できません。これらはクラスコンポーネントでのみ使用できます。また、機能コンポーネントでのみ使用できるフック。 React docの以下の行

Reactクラスのライフサイクルメソッドに精通している場合、useEffectフックはcomponentDidMount、componentDidUpdate、およびcomponentWillUnmountを組み合わせたものと考えることができます。

機能コンポーネントのクラスコンポーネントからこれらのライフサイクルメソッドを模倣できることをお勧めします。

componentDidMount内のコードは、コンポーネントがマウントされたときに1回実行されます。この動作に相当するuseEffectフックは

useEffect(() => {
  // Your code here
}, []);

2番目のパラメーター(空の配列)に注意してください。これは一度だけ実行されます。

2番目のパラメーターなし useEffectフックは、危険な可能性のあるコンポーネントのすべてのレンダリングで呼び出されます。

useEffect(() => {
  // Your code here
});

componentWillUnmountは、クリーンアップ(イベントリスナの削除、タイマーのキャンセルなど)に使用されます。以下のように、componentDidMountにイベントリスナを追加し、componentWillUnmountでイベントリスナを削除するとします。

componentDidMount() {
  window.addEventListener('mousemove', () => {})
}

componentWillUnmount() {
  window.removeEventListener('mousemove', () => {})
}

上記のコードに相当するフックは次のようになります

useEffect(() => {
  window.addEventListener('mousemove', () => {});

  // returned function will be called on component unmount 
  return () => {
    window.removeEventListener('mousemove', () => {})
  }
}, [])
106

Reactjs.orgによると、componentWillMountは将来サポートされなくなります。 https://reactjs.org/docs/react-component.html#unsafe_componentwillmount

ComponentWillMountを使用する必要はありません。

コンポーネントがマウントされる前に何かをしたい場合は、constructor()でそれを行ってください。

ネットワーク要求を実行する場合は、componentWillMountで実行しないでください。これは、これを行うと予期しないバグが発生するためです。

ネットワーク要求は、componentDidMountで実行できます。

それが役に立てば幸い。


2019年8月3日に更新

ComponentWillMountを要求する理由は、おそらくレンダリング前に状態を初期化するためです。

UseStateで実行してください。

        const helloWorld=()=>{
           const [value,setValue]=useState(0) //initialize your state here
            return <p>{value}</p>
            }
         export default helloWorld;

または、元のコードが次のようになっている場合など、componentWillMountで関数を実行したい場合があります。

  componentWillMount(){
    console.log('componentWillMount')
    }

フックを使用して、ライフサイクルメソッドを削除するだけです。

    const hookComponent=()=>{
       console.log('componentWillMount')
       return <p>you have transfered componeWillMount from class component into hook </p>
    }

UseEffectに関する最初の回答に何かを追加したいだけです。

useEffect(()=>{})

useEffectはすべてのレンダリングで実行され、componentDidUpdate、componentDidMount、ComponentWillUnmountの組み合わせです。

 useEffect(()=>{},[])

UseEffectに空の配列を追加すると、コンポーネントがマウントされたときに実行されます。 useEffectは、渡された配列を比較するためです。したがって、空の配列である必要はありません。変更されていない配列でもかまいません。たとえば、[1,2,3]または['1,2']です。 useEffectは、コンポーネントがマウントされている場合にのみ実行されます。

一度だけ実行するか、すべてのレンダリング後に実行するかは、あなた次第です。何をしているのかを知っている限り、配列を追加するのを忘れても危険ではありません。

フック用のサンプルを作成しました。チェックアウトしてください。

https://codesandbox.io/s/kw6xj153wr


2019年8月21日に更新

上記の答えを書いてから白くなってきました。あなたが注意を払う必要があると思うものがあります。使用するとき

useEffect(()=>{},[])

Reactが配列[]に渡した値を比較するとき、Object.is()を使用して比較します。次のようなオブジェクトを渡した場合

useEffect(()=>{},[{name:'Tom'}])

これはまったく同じです:

useEffect(()=>{})

Object.is()がオブジェクトを比較するとき、値自体ではなくその参照を比較するため、毎回再レンダリングされます。参照が異なるため、{} === {}がfalseを返す理由と同じです。参照ではなくオブジェクト自体を比較したい場合は、次のようなことができます。

useEffect(()=>{},[JSON.stringify({name:'Tom'})])
21
MING WU

useLayoutEffectは、機能が実際にcomponentWillMountに類似している場合、オブザーバーの空のセット([])でこれを実現できます。最初のコンテンツがDOMに到達する前に実行されます。実際には2つの更新ですが、画面に描画する前に同期されます。

例えば:


function MyComponent({ ...andItsProps }) {
     useLayoutEffect(()=> {
          console.log('I am about to render!');
     },[]);

     return (<div>some content</div>);
}

イニシャライザー/セッターまたはuseStateを使用したuseEffectに対する利点は、レンダーパスを計算できますが、ユーザーが気付くDOMへの実際の再レンダーはなく、実行されることです- beforeuseEffectの場合ではない最初の注目すべきレンダリング。欠点はもちろん、画面にペイントする前にチェック/更新を行う必要があるため、最初のレンダリングのわずかな遅延です。ただし、実際にはユースケースに依存します。

個人的に、useMemoは、何か重いことをする必要がある特定のニッチなケースでは問題ないことを考えます。

6
rob2d

useComponentDidMountフック

ほとんどの場合、useComponentDidMountが使用するツールです。コンポーネントがマウントされた後(初期レンダリング)、一度だけ実行されます。

 const useComponentDidMount = func => useEffect(func, []);

useComponentWillMount

クラスのコンポーネントcomponentWillMountはレガシーと見なされることに注意することが重要です。コンポーネントがマウントされる前に一度だけコードを実行する必要がある場合は、コンストラクターを使用できます。 詳細はこちら 。機能コンポーネントにはコンストラクタと同等の機能がないため、特定の場合、コンポーネントをマウントする前にフックを使用してコードを1回だけ実行するのが理にかなっています。カスタムフックでそれを実現できます。

const useComponentWillMount = func => {
  const willMount = useRef(true);

  if (willMount.current) {
    func();
  }

  useComponentDidMount(() => {
    willMount.current = false;
  });
};

ただし、落とし穴があります。非同期に状態を設定するためにそれを使用しないでください(例えば、サーバーリクエストに続く。最初のレンダリングに影響すると予想されるかもしれませんが、そうしません)。このような場合は、useComponentDidMountで処理する必要があります。

デモ

const Component = (props) => {
  useComponentWillMount(() => console.log("Runs only once before component mounts"));
  useComponentDidMount(() => console.log("Runs only once after component mounts"));
  ...

  return (
    <div>{...}</div>
  );
}

完全なデモ

2
Ben Carp

最初のレンダリングの前に関数を1回実行するカスタムフックを作成しました。

useBeforeFirstRender.js

import { useState, useEffect } from 'react'

export default (fun) => {
  const [hasRendered, setHasRendered] = useState(false)

  useEffect(() => setHasRendered(true), [hasRendered])

  if (!hasRendered) {
    fun()
  }
}

使用法:

import React, { useEffect } from 'react'
import useBeforeFirstRender from '../hooks/useBeforeFirstRender'


export default () => (
  useBeforeFirstRender(() => {
    console.log('Do stuff here')
  })

  return (
    <div>
      My component
    </div>
  )
)
1
Littletime

https://reactjs.org/docs/hooks-reference.html#usememo

UseMemoに渡された関数はレンダリング中に実行されることに注意してください。レンダリング中に通常はしないことは何もしないでください。たとえば、副作用はuseMemoではなくuseEffectに属します。

0
user11041494