関数コンポーネント内のReactJSライフサイクルメソッド


134

クラス内にコンポーネントを記述する代わりに、関数構文を使用したいと思います。

関数コンポーネント内でをオーバーライドするにcomponentDidMountはどうすればよいcomponentWillMountですか?
可能ですか?

const grid = (props) => {
    console.log(props);
    let {skuRules} = props;

    const componentDidMount = () => {
        if(!props.fetched) {
            props.fetchRules();
        }
        console.log('mount it!');
    };
    return(
        <Content title="Promotions" breadcrumbs={breadcrumbs} fetched={skuRules.fetched}>
            <Box title="Sku Promotion">
                <ActionButtons buttons={actionButtons} />
                <SkuRuleGrid 
                    data={skuRules.payload}
                    fetch={props.fetchSkuRules}
                />
            </Box>      
        </Content>  
    )
}

1
機能コンポーネントにはライフサイクルメソッドはありません。それらは単なる関数だからです。関数にはメソッドがありません。そのためのクラスがあります
雪崩

回答:


148

編集:の導入によりHooks、それが行動のライフサイクルの種類だけでなく、機能性成分で状態を実現することが可能です。現在

フックは、クラスを作成せずに状態やその他のReact機能を使用できるようにする新しい機能の提案です。これらはv16.8.0の一部としてReactでリリースされています。

useEffectフックは、ライフサイクルの動作を複製useStateするために使用でき、状態を関数コンポーネントに格納するために使用できます。

基本的な構文:

useEffect(callbackFunction, [dependentProps]) => cleanupFunction

次のようなフックでユースケースを実装できます

const grid = (props) => {
    console.log(props);
    let {skuRules} = props;

    useEffect(() => {
        if(!props.fetched) {
            props.fetchRules();
        }
        console.log('mount it!');
    }, []); // passing an empty array as second argument triggers the callback in useEffect only after the initial render thus replicating `componentDidMount` lifecycle behaviour

    return(
        <Content title="Promotions" breadcrumbs={breadcrumbs} fetched={skuRules.fetched}>
            <Box title="Sku Promotion">
                <ActionButtons buttons={actionButtons} />
                <SkuRuleGrid 
                    data={skuRules.payload}
                    fetch={props.fetchSkuRules}
                />
            </Box>      
        </Content>  
    )
}

useEffectコンポーネントがアンマウントされたときに実行される関数を返すこともできます。これを使用して、リスナーのサブスクリプションを解除し、動作を複製できます。componentWillUnmount

例:componentWillUnmount

useEffect(() => {
    window.addEventListener('unhandledRejection', handler);
    return () => {
       window.removeEventListener('unhandledRejection', handler);
    }
}, [])

useEffect特定のイベントを条件とするために、変更を確認するための値の配列をイベントに提供できます。

例:componentDidUpdate

componentDidUpdate(prevProps, prevState) {
     const { counter } = this.props;
     if (this.props.counter !== prevState.counter) {
      // some action here
     }
}

同等のフック

useEffect(() => {
     // action here
}, [props.counter]); // checks for changes in the values in this array

この配列を含める場合は、時間の経過とともに変化するコンポーネントスコープのすべての値(props、state)を必ず含めてください。そうしないと、以前のレンダリングの値を参照してしまう可能性があります。

の使用にはいくつかの微妙な点がありuseEffectます。APIを確認してくださいHere


v16.7.0より前

関数コンポーネントの特性は、Reactsライフサイクル関数またはthisキーワードにアクセスできないことです。React.Componentライフサイクル関数を使用する場合は、クラスを拡張する必要があります。

class Grid extends React.Component  {
    constructor(props) {
       super(props)
    }

    componentDidMount () {
        if(!this.props.fetched) {
            this.props.fetchRules();
        }
        console.log('mount it!');
    }
    render() {
    return(
        <Content title="Promotions" breadcrumbs={breadcrumbs} fetched={skuRules.fetched}>
            <Box title="Sku Promotion">
                <ActionButtons buttons={actionButtons} />
                <SkuRuleGrid 
                    data={skuRules.payload}
                    fetch={props.fetchSkuRules}
                />
            </Box>      
        </Content>  
    )
  }
}

関数コンポーネントは、追加のロジックを必要とせずにコンポーネントをレンダリングするだけの場合に役立ちます。


1
すでに述べたように、コンポーネントにロジックがあり、ライフサイクル関数を使用するように要求されているため、functioanlコンポーネントではそれを実行できません。だからクラスを利用する方がいい。コンポーネントに追加のロジックが含まれていない場合は機能コンポーネントを使用する
Shubham Khatri

1
これは、componentDidUpdateとまったく同じではないことに注意してください。useEffect(() => { // action here }, [props.counter])最初のレンダリング時にトリガーされますが、componentDidUpdateはトリガーされません。
Estus Flask

1
passing an empty array as second argument triggers the callback in useEffect only after the initial renderこれは、物事を構築するための汚いハックな方法のように聞こえます:/うまくいけば、反応チームは将来のリリースでより良いものを思いつくでしょう。
Lukas Liesis、

3
そう?あなたがcomponentwillmountでコードを実行する方法に答える部分はどこですか?
トスカン

59

react-pure-lifecycleを使用して、機能コンポーネントにライフサイクル機能を追加できます。

例:

import React, { Component } from 'react';
import lifecycle from 'react-pure-lifecycle';

const methods = {
  componentDidMount(props) {
    console.log('I mounted! Here are my props: ', props);
  }
};

const Channels = props => (
<h1>Hello</h1>
)

export default lifecycle(methods)(Channels);

3
なにGrid?コードスニペットのどこにも定義されていませんか?これと一緒にreduxを使用したい場合は、次のようなものを回避できますexport default lifecycle(methods)(connect({},{})(ComponentName))か?
Sean Clancy

@SeanClancy返信が遅くなってすみません。コードスニペットが更新されました。
ヨハン

1
これは良い習慣だと思いますか?これに到達する前に別の解決策を試す必要がありますか、それとも最も簡単な場合はそれを使用しても大丈夫ですか?
SuperSimplePimpleDimple

9

ソリューション1: 新しいHOOKS APIを使用できます。現在React v16.8.0にあります

フックを使用すると、クラスなしでReactの機能をさらに使用できます。 フックは、プロップ、状態、コンテキスト、参照、ライフサイクルなど、すでに知っているReactの概念に、より直接的なAPIを提供します。フックは、再構成で対処されるすべての問題を解決します。

作者からのメモrecompose(acdlite、2018年10月25日):

こんにちは!約3年前にRecomposeを作成しました。その約1年後、Reactチームに参加しました。本日、フックの提案を発表しました。Hooksは、3年前にRecomposeで対処しようとしたすべての問題を解決します。このパッケージのアクティブなメンテナンスを中止し(将来のReactリリースとの互換性のためのバグ修正やパッチを除く)、代わりにフックを使用することをお勧めします。Recomposeを使用した既存のコードは引き続き機能しますが、新機能はありません。

解決策2:

フックをサポートしていない反応バージョンを使用している場合、心配はありませんrecompose。代わりに(関数コンポーネントと高次コンポーネントのReactユーティリティベルト)を使用してください。関数コンポーネントへのrecomposeアタッチlifecycle hooks, state, handlers etcに使用できます。

以下は、ライフサイクルHOCを介してライフサイクルメソッドをアタッチするレンダリングなしのコンポーネントです(再構成から)。

// taken from https://gist.github.com/tsnieman/056af4bb9e87748c514d#file-auth-js-L33

function RenderlessComponent() {
  return null; 
}

export default lifecycle({

  componentDidMount() {
    const { checkIfAuthed } = this.props;
    // Do they have an active session? ("Remember me")
    checkIfAuthed();
  },

  componentWillReceiveProps(nextProps) {
    const {
      loadUser,
    } = this.props;

    // Various 'indicators'..
    const becameAuthed = (!(this.props.auth) && nextProps.auth);
    const isCurrentUser = (this.props.currentUser !== null);

    if (becameAuthed) {
      loadUser(nextProps.auth.uid);
    }

    const shouldSetCurrentUser = (!isCurrentUser && nextProps.auth);
    if (shouldSetCurrentUser) {
      const currentUser = nextProps.users[nextProps.auth.uid];
      if (currentUser) {
        this.props.setCurrentUser({
          'id': nextProps.auth.uid,
          ...currentUser,
        });
      }
    }
  }
})(RenderlessComponent);

4

独自のライフサイクルメソッドを作成できます。

ユーティリティ関数

import { useEffect, useRef } from "react";

export const componentDidMount = handler => {
  return useEffect(() => {
    return handler();
  }, []);
};

export const componentDidUpdate = (handler, deps) => {
  const isInitialMount = useRef(true);

  useEffect(() => {
    if (isInitialMount.current) {
      isInitialMount.current = false;

      return;
    }

    return handler();
  }, deps);
};

使用法

import { componentDidMount, componentDidUpdate } from "./utils";

export const MyComponent = ({ myProp }) => {
  componentDidMount(() => {
    console.log("Component did mount!");
  });

  componentDidUpdate(() => {
    console.log("Component did update!");
  });

  componentDidUpdate(() => {
    console.log("myProp did update!");
  }, [myProp]);
};  

2

ドキュメントによると:

import React, { useState, useEffect } from 'react'
// Similar to componentDidMount and componentDidUpdate:

useEffect(() => {


});

Reactのドキュメントを参照してください


0

React LifeCycleを使用する必要がある場合は、Classを使用する必要があります。

サンプル:

import React, { Component } from 'react';

class Grid extends Component {

 constructor(props){
  super(props)
 }

 componentDidMount () { /* do something */ }

 render () { 
   return <h1>Hello</h1>
 }

}

2
クラスを使いたくない。
Aftab Naveed 2017年

3
問題は、クラスではなく機能コンポーネントでライフサイクルメソッドを使用する方法でした。
Mike

現在、React Hooksを使用
Gabriel Ferreira

0

create-react-classモジュールを利用できます。 公式ドキュメント

もちろん、最初にインストールする必要があります

npm install create-react-class

これが実際の例です

import React from "react";
import ReactDOM from "react-dom"
let createReactClass = require('create-react-class')


let Clock = createReactClass({
    getInitialState:function(){
        return {date:new Date()}
    },

    render:function(){
        return (
            <h1>{this.state.date.toLocaleTimeString()}</h1>
        )
    },

    componentDidMount:function(){
        this.timerId = setInterval(()=>this.setState({date:new Date()}),1000)
    },

    componentWillUnmount:function(){
        clearInterval(this.timerId)
    }

})

ReactDOM.render(
    <Clock/>,
    document.getElementById('root')
)

0

react 16.8を使用している場合、reactフックを使用できます... Reactフックは、関数コンポーネントからReactの状態とライフサイクル機能に「フック」できる関数です... docs

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.