ComponentDidMountはReact関数/フックコンポーネントと同等ですか?


回答:


216

フックの安定バージョンの場合(Reactバージョン16.8.0以降)

にとって componentDidMount

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

にとって componentDidUpdate

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

にとって componentWillUnmount

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

したがって、この状況では、依存関係をこの配列に渡す必要があります。あなたがこのような状態にあると仮定しましょう

const [count, setCount] = useState(0);

また、カウントが増えるたびに、関数コンポーネントを再レンダリングする必要があります。その後、あなたuseEffectはこのように見えるはずです

useEffect(() => {
  // <div>{count}</div>
}, [count]);

このようにして、カウントが更新されるたびに、コンポーネントが再レンダリングされます。うまくいけば、これは少し役立つでしょう。


徹底説明!componentDidReceivePropsをシミュレートする方法はありますか?
jeyko

1
たとえ存在しても気づいていません。このスレッドで確認できます。github.com
facebook /

1
の2番目の引数を知らなかったので、これをありがとうuseState。これを読んでいる人は、2番目の引数を残すと、undefinedすべてのレンダリングでエフェクトがトリガーされることに注意してください(私が間違っていない場合)。
dimiguel

useEffectの依存関係(依存関係配列を渡す)を意味しますか?もしそうなら、それを空のままにしておくと、それはコードのバグです。この例ではcountが状態変数であり、setCountがその状態を更新する関数であるため、配列の分解には[count、setCount]の両方が必要です。
MertcanDiken19年

1
空の依存関係配列を使用してcomponentDidMountをシミュレートしようとしています。問題は、通常、「React Hook useEffectに依存関係がありません:<some prop>。それを含めるか、依存関係配列react-hooks / exhaustive-depsを削除してください」という警告が表示されることです。提案された「修正」のいずれかを適用すると、componentDidMountとして動作しなくなります。私は何か間違ったことをしていますか?
JonasRosenqvist20年

3

受け入れられた回答は機能しますが、お勧めしません。複数の状態があり、それをuseEffectで使用すると、依存関係配列に追加するか、まったく使用しないかについて警告が表示されます。

それは時々あなたに予測できない出力を与えるかもしれない問題を引き起こします。したがって、関数をクラスとして書き直すために少し努力することをお勧めします。変更はほとんどなく、一部のコンポーネントをクラスとして、一部を関数として使用できます。規則を1つだけ使用する義務はありません。

これを例に取ってください

function App() {
  const [appointments, setAppointments] = useState([]);
  const [aptId, setAptId] = useState(1);

  useEffect(() => {
    fetch('./data.json')
      .then(response => response.json())
      .then(result => {
        const apts = result.map(item => {
          item.aptId = aptId;
          console.log(aptId);
          setAptId(aptId + 1);
          return item;
        })
        setAppointments(apts);
      });
  }, []);

  return(...);
}

そして

class App extends Component {
  constructor() {
    super();
    this.state = {
      appointments: [],
      aptId: 1,
    }
  }

  componentDidMount() {
    fetch('./data.json')
      .then(response => response.json())
      .then(result => {
        const apts = result.map(item => {
          item.aptId = this.state.aptId;
          this.setState({aptId: this.state.aptId + 1});
          console.log(this.state.aptId);
          return item;
        });
        this.setState({appointments: apts});
      });
  }

  render(...);
}

これはほんの一例です。そのため、コードのベストプラクティスや潜在的な問題については話さないでください。これは両方とも同じロジックを持っていますが、後者は期待どおりにしか機能しません。今回はuseEffectを実行してcomponentDidMount機能を取得する可能性がありますが、アプリが大きくなるにつれて、いくつかの問題に直面する可能性があります。したがって、その段階で書き直すよりも、早い段階でこれを行う方がよいでしょう。

その上、OOPはそれほど悪くはありません。プロシージャ指向プログラミングで十分であれば、オブジェクト指向プログラミングはありませんでした。それは時々苦痛ですが、より良いです(技術的には個人的な問題は別として)。


1
これは私がしました。フックの使用で問題が発生しました。この問題は、クラスに変換した後に解消されました。
Julez

2

componentDidMount機能的なコンポーネントはありませんが、Reactフックは、useEffectフックを使用して動作をエミュレートする方法を提供します。

useEffect()マウントでのみコールバックのみを実行するには、2番目の引数として空の配列を渡します。

ドキュメントをuseEffectお読みください。

function ComponentDidMount() {
  const [count, setCount] = React.useState(0);
  React.useEffect(() => {
    console.log('componentDidMount');
  }, []);

  return (
    <div>
      <p>componentDidMount: {count} times</p>
      <button
        onClick={() => {
          setCount(count + 1);
        }}
      >
        Click Me
      </button>
    </div>
  );
}

ReactDOM.render(
  <div>
    <ComponentDidMount />
  </div>,
  document.querySelector("#app")
);
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>


1

componentDidMountinreactフックに完全に相当するものはありません。


私の経験では、reactフックはそれを開発するときに異なる考え方を必要とし、一般的に言えば、のようなクラスメソッドと比較するべきではありませんcomponentDidMount

そうは言っても、フックを使用してと同様の効果生み出す方法がいくつかありますcomponentDidMount

解決策1:解決策1:

useEffect(() => {
  console.log("I have been mounted")
}, [])

解決策2:解決策2:

const num = 5

useEffect(() => {
  console.log("I will only run if my deps change: ", num)
}, [num])

解決策3(機能付き):

useEffect(() => {
  const someFunc = () => {
    console.log("Function being run after/on mount")
  }
  someFunc()
}, [])

解決策4(useCallback):

const msg = "some message"

const myFunc = useCallback(() => {
  console.log(msg)
}, [msg])

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

解決策5(創造性を発揮する):

export default function useDidMountHook(callback) {
  const didMount = useRef(null)

  useEffect(() => {
    if (callback && !didMount.current) {
      didMount.current = true
      callback()
    }
  })
}

ソリューション5は、他のどのソリューションもユースケースで機能しない場合にのみ実際に使用する必要があることに注意してください。ソリューション5が必要だと判断した場合は、この既製のフックuse-did-mountを使用することをお勧めします。

ソース(詳細):reactフックでのcomponentDidMountの使用


0

componentDidMount()の正確に同等のフックは

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

これがお役に立てば幸いです:)


-1

あなたは利用したいuseEffect()あなたは関数を使用する方法に応じて、)(ちょうどcomponentDidMountのように振る舞うことができ、。

例えば。loaded最初はfalseに設定されているカスタム状態プロパティを使用し、レンダリング時にtrueに切り替えて、この値が変更された場合にのみエフェクトを起動できます。

ドキュメンテーション


1
このソリューションは理想的ではありません。コンポーネントがマウントされているかどうかを判断するためだけに状態値を使用することはお勧めできません。また、プロパティを使用する場合は、別の再レンダリングをトリガーしないため、refの方が適しています。
ヤンシュンテイ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.