Bir işlev bileşeni içindeki ReactJS yaşam döngüsü yöntemi


135

Bileşenlerimi bir sınıfın içine yazmak yerine, bunun yerine işlev sözdizimini kullanmak istiyorum.

Nasıl geçersiz yok componentDidMount, componentWillMountişlev bileşenlerinin iç?
Hatta mümkün mü?

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
işlevsel bileşenlerin yaşam döngüsü yöntemlerine sahip olmaması gerekir. çünkü bunlar sadece işlevlerdir. ve fonksiyonların metotları yoktur. bunun için sınıflar var
çığ 1

Yanıtlar:


149

Düzenleme: Tanıtımı ile, Hooksbir yaşam döngüsü türü davranışın yanı sıra işlevsel Bileşenlerdeki durumu uygulamak mümkündür. Şu anda

Hook'lar, bir sınıf yazmadan state'i ve diğer React özelliklerini kullanmanıza izin veren yeni bir özellik teklifidir. React'te v16.8.0'ın bir parçası olarak yayınlanırlar

useEffecthook, yaşam döngüsü davranışını kopyalamak useStateiçin kullanılabilir ve durumu bir işlev bileşeninde depolamak için kullanılabilir.

Temel sözdizimi:

useEffect(callbackFunction, [dependentProps]) => cleanupFunction

Kullanım durumunuzu aşağıdaki gibi kancalara uygulayabilirsiniz

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

useEffectbileşen ayrıldığında çalışacak bir işlev de döndürebilir. Bu, aşağıdaki davranışları tekrarlayarak dinleyicilere aboneliğinizi iptal etmek için kullanılabilir componentWillUnmount:

Örneğin: componentWillUnmount

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

useEffectBelirli olaylara koşullu yapmak için, değişiklikleri kontrol etmek için ona bir dizi değer sağlayabilirsiniz:

Örneğin: componentDidUpdate

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

Kancalar Eşdeğeri

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

Bu diziyi dahil ederseniz, bileşen kapsamındaki zamanla değişen (props, durum) tüm değerleri dahil ettiğinizden emin olun, aksi takdirde önceki işlemelerden değerlere referans verebilirsiniz.

Kullanılacak bazı incelikler var useEffect; API'ye bakın Here.


V16.7.0'dan önce

İşlev bileşenlerinin özelliği, Reacts yaşam döngüsü işlevlerine veya thisanahtar sözcüğe erişimlerinin olmamasıdır . React.ComponentYaşam döngüsü işlevini kullanmak istiyorsanız sınıfı genişletmeniz gerekir .

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

Fonksiyon bileşenleri, yalnızca Bileşeninizi ekstra mantığa ihtiyaç duymadan işlemek istediğinizde kullanışlıdır.


1
Dediğim gibi, bileşeninizde bir mantığınız var ve gereksiniminiz bir yaşam döngüsü işlevi kullanmanızı istiyor ve bunu functioanl bileşenlerle yapamazsınız. Bu yüzden sınıftan daha iyi yararlanın. Bileşeniniz fazladan mantık içermediğinde işlevsel bileşeni kullanın
Shubham Khatri

1
Bunun tam componentDidUpdate eşdeğeri olmadığına dikkat edilmelidir. useEffect(() => { // action here }, [props.counter])componentDidUpdate tetiklenmezken ilk oluşturma sırasında tetiklenir.
Estus Flask

1
passing an empty array as second argument triggers the callback in useEffect only after the initial renderbu bir şeyler inşa etmenin kirli bir yoluna benziyor: / umarım tepki ekibi gelecek sürümlerde daha iyi bir şey bulacaktır.
Lukas Liesis

3
yani? componentwillmount üzerinde kodun nasıl çalıştırılacağını yanıtladığınız bölüm nerede?
Toskan

59

İşlevsel bileşenlere yaşam döngüsü işlevleri eklemek için react-pure-yaşam döngüsünü kullanabilirsiniz.

Misal:

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
Nedir Grid? Kod pasajınızda herhangi bir yerde tanımlanmış görmüyorum? Redux'u bununla da kullanmak istersen, gibi bir şeyden kurtulabilir misin export default lifecycle(methods)(connect({},{})(ComponentName))?
Sean Clancy

@SeanClancy Geç yanıt için özür dilerim. Kod pasajı güncellendi.
Yohann

1
Bu iyi bir uygulama olarak kabul ediliyor mu? Buna ulaşmadan önce farklı çözümler denemeli miyim yoksa en kolay bulursam kullanmam uygun mudur?
SuperSimplePimpleDimple

9

Birinci Çözüm: Yeni react HOOKS API kullanabilirsiniz. Şu anda React v16.8.0 sürümünde

Hook'lar, React'in daha fazla özelliğini sınıflar olmadan kullanmanıza izin verir. Hook'lar, zaten bildiğiniz React kavramlarına daha doğrudan bir API sağlar: props, state, context, refs ve lifecycle . Hooks, Recompose ile ele alınan tüm sorunları çözer.

Yazarın Notu recompose(acdlite, 25 Ekim 2018):

Selam! Recompose'u yaklaşık üç yıl önce yarattım. Bundan yaklaşık bir yıl sonra React ekibine katıldım. Bugün Hooks için bir teklif duyurduk. Hooks, üç yıl önce Recompose ile çözmeye çalıştığım tüm sorunları ve dahasını çözüyor. Bu paketin aktif bakımına devam etmeyeceğim (belki de gelecekteki React sürümleriyle uyumluluk için hata düzeltmeleri veya yamalar hariç) ve bunun yerine insanların Hook'ları kullanmasını tavsiye edeceğim. Recompose ile mevcut kodunuz çalışmaya devam edecek, herhangi bir yeni özellik beklemeyin.

İkinci Çözüm:

Kancaları desteklemeyen react versiyonunu kullanıyorsanız endişelenmeyin, recomposebunun yerine (Fonksiyon bileşenleri ve daha yüksek seviye bileşenler için bir React yardımcı kemeri) kullanın. Bir fonksiyon bileşenine recomposeeklemek lifecycle hooks, state, handlers etciçin kullanabilirsiniz .

Burada , yaşam döngüsü HOC aracılığıyla (yeniden oluşturmadan) yaşam döngüsü yöntemlerini ekleyen oluşturmasız bir bileşen var .

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

Kendi yaşam döngüsü yöntemlerinizi oluşturabilirsiniz.

Fayda fonksiyonları

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

kullanım

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

Belgelere göre:

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

useEffect(() => {


});

React belgelerine bakın


0

React LifeCycle'ı kullanmanız gerekiyorsa, Class'ı kullanmanız gerekir.

Örneklem:

import React, { Component } from 'react';

class Grid extends Component {

 constructor(props){
  super(props)
 }

 componentDidMount () { /* do something */ }

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

}

2
Sınıfı kullanmak istemiyorum.
Aftab Naveed

3
Sorun, yaşam döngüsü yöntemlerinin bir sınıfla değil, işlevsel bir bileşenle nasıl kullanılacağıydı.
Mike

Şimdi, React Hooks ile
Gabriel Ferreira

0

Create-react-class modülünden yararlanabilirsiniz. Resmi belgeler

Tabii ki önce yüklemelisin

npm install create-react-class

İşte çalışan bir örnek

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 kullanıyorsanız, react Hook'larını kullanabilirsiniz ... React Hook'lar, React durumu ve işlev bileşenlerinden yaşam döngüsü özelliklerini "bağlamanıza" izin veren işlevlerdir ... docs

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.