Metode siklus hidup ReactJS di dalam Komponen fungsi


135

Alih-alih menulis komponen saya di dalam kelas, saya ingin menggunakan sintaks fungsi sebagai gantinya.

Bagaimana cara mengganti componentDidMount, componentWillMountdi dalam komponen fungsi?
Apakah itu mungkin?

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
komponen fungsional tidak seharusnya memiliki metode siklus hidup. karena itu hanyalah fungsi. dan fungsi tidak memiliki metode. ada kelas untuk itu
longsoran

Jawaban:


149

Sunting: Dengan pengenalan Hooksitu mungkin untuk mengimplementasikan jenis siklus hidup perilaku serta negara dalam Komponen fungsional. Saat ini

Hooks adalah proposal fitur baru yang memungkinkan Anda menggunakan status dan fitur React lainnya tanpa menulis kelas. Mereka dirilis di React sebagai bagian dari v16.8.0

useEffecthook dapat digunakan untuk mereplikasi perilaku siklus proses, dan useStatedapat digunakan untuk menyimpan status dalam komponen fungsi.

Sintaks dasar:

useEffect(callbackFunction, [dependentProps]) => cleanupFunction

Anda dapat menerapkan kasus penggunaan Anda dalam kait seperti

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>  
    )
}

useEffectjuga dapat mengembalikan fungsi yang akan dijalankan saat komponen dilepas. Ini dapat digunakan untuk berhenti berlangganan pendengar, meniru perilaku componentWillUnmount:

Misalnya: componentWillUnmount

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

Untuk membuat useEffectkondisional pada peristiwa tertentu, Anda dapat menyediakannya dengan array nilai untuk memeriksa perubahan:

Misalnya: componentDidUpdate

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

Hooks Equivalent

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

Jika Anda menyertakan larik ini, pastikan untuk menyertakan semua nilai dari lingkup komponen yang berubah seiring waktu (alat peraga, status), atau Anda mungkin akhirnya mereferensikan nilai dari render sebelumnya.

Ada beberapa kehalusan untuk digunakan useEffect; lihat API Here.


Sebelum v16.7.0

Properti komponen fungsi adalah mereka tidak memiliki akses ke fungsi siklus hidup Reacts atau thiskata kunci. Anda perlu memperluas React.Componentkelas jika ingin menggunakan fungsi siklus proses.

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>  
    )
  }
}

Komponen fungsi berguna ketika Anda hanya ingin merender Komponen tanpa memerlukan logika tambahan.


1
Seperti yang saya katakan, Anda memiliki logika dalam komponen Anda dan kebutuhan Anda ingin Anda menggunakan fungsi siklus hidup dan Anda tidak dapat melakukannya dengan komponen functioanl. Jadi lebih baik manfaatkan kelas. Gunakan komponen fungsional bila komponen Anda tidak berisi logika tambahan
Shubham Khatri

1
Perlu diperhatikan bahwa ini bukan komponen yang sama persis dengan componentDidUpdate. useEffect(() => { // action here }, [props.counter])dipicu pada render awal sedangkan componentDidUpdate tidak.
Estus Flask

1
passing an empty array as second argument triggers the callback in useEffect only after the initial renderini terdengar seperti cara hacky yang kotor untuk membangun sesuatu: / semoga tim yang bereaksi akan menghasilkan sesuatu yang lebih baik di rilis mendatang.
Lukas Liesis

3
begitu? di mana bagian di mana Anda menjawab bagaimana menjalankan kode di componentwillmount?
Toskan

59

Anda dapat menggunakan react-pure-lifecycle untuk menambahkan fungsi siklus hidup ke komponen fungsional.

Contoh:

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
Apa Grid? Saya tidak melihatnya didefinisikan di mana pun di cuplikan kode Anda? Jika Anda ingin menggunakan redux dengan ini juga, bisakah Anda lolos dengan sesuatu seperti export default lifecycle(methods)(connect({},{})(ComponentName))?
Sean Clancy

@SeanClancy Maaf atas tanggapan yang terlambat. Potongan kode telah diperbarui.
Yohann

1
Apakah ini dianggap praktik yang baik? Haruskah saya mencoba solusi yang berbeda sebelum saya meraih yang ini atau apakah boleh menggunakannya jika menurut saya paling mudah?
SuperSimplePimpleDimple

9

Solusi Satu: Anda dapat menggunakan API HOOKS react baru . Saat ini di React v16.8.0

Hooks memungkinkan Anda menggunakan lebih banyak fitur React tanpa kelas. Hooks menyediakan API yang lebih langsung ke konsep React yang sudah Anda ketahui: props, state, context, refs, dan lifecycle . Hooks memecahkan semua masalah yang diatasi dengan Recompose.

Catatan dari Penulis recompose(acdlite, 25 Okt 2018):

Hai! Saya membuat Recompose sekitar tiga tahun lalu. Sekitar setahun setelah itu, saya bergabung dengan tim React. Hari ini, kami mengumumkan proposal untuk Hooks. Hooks memecahkan semua masalah yang saya coba atasi dengan Recompose tiga tahun lalu, dan lebih dari itu. Saya akan menghentikan pemeliharaan aktif dari paket ini (mungkin tidak termasuk perbaikan bug atau patch untuk kompatibilitas dengan rilis React di masa mendatang), dan merekomendasikan agar orang-orang menggunakan Hooks sebagai gantinya. Kode Anda yang ada dengan Recompose akan tetap berfungsi, tapi jangan berharap ada fitur baru.

Solusi Kedua:

Jika Anda menggunakan versi react yang tidak mendukung hook, jangan khawatir, gunakan recompose(Sabuk utilitas React untuk komponen fungsi dan komponen tingkat tinggi.) Sebagai gantinya. Anda dapat menggunakan recomposeuntuk melampirkan lifecycle hooks, state, handlers etcke komponen fungsi.

Berikut adalah komponen tanpa render yang melampirkan metode siklus proses melalui siklus proses HOC (dari komposisi ulang).

// 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

Anda dapat membuat metode siklus proses Anda sendiri.

Fungsi utilitas

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);
};

Pemakaian

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

Menurut dokumentasi:

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

useEffect(() => {


});

lihat dokumentasi React


0

Jika Anda perlu menggunakan React LifeCycle, Anda perlu menggunakan Class.

Sampel:

import React, { Component } from 'react';

class Grid extends Component {

 constructor(props){
  super(props)
 }

 componentDidMount () { /* do something */ }

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

}

2
Saya tidak ingin menggunakan kelas.
Aftab Naveed

3
Pertanyaannya adalah bagaimana menggunakan metode siklus hidup dengan komponen fungsional, bukan kelas.
Mike

Sekarang, dengan React Hooks
Gabriel Ferreira

0

Anda dapat menggunakan modul create-react-class. Dokumentasi resmi

Tentu Anda harus menginstalnya terlebih dahulu

npm install create-react-class

Berikut adalah contoh yang berfungsi

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

jika Anda menggunakan react 16.8, Anda dapat menggunakan react Hooks ... React Hooks adalah fungsi yang memungkinkan Anda “terhubung ke” status React dan fitur siklus hidup dari komponen fungsi ... docs

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.