206 votes

Méthode de cycle de vie ReactJS à l'intérieur d'une fonction Composant

Au lieu d'écrire mes composants dans une classe, j'aimerais utiliser la syntaxe des fonctions.

Comment puis-je passer outre componentDidMount , componentWillMount à l'intérieur des composants de la fonction ?
Est-ce même possible ?

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

3 votes

Les composants fonctionnels ne sont pas censés avoir des méthodes de cycle de vie. parce qu'ils sont juste des fonctions. et les fonctions n'ont pas de méthodes. il y a des classes pour cela

241voto

Shubham Khatri Points 67350

Editar: Avec l'introduction de Hooks il est possible d'implémenter un comportement de type cycle de vie ainsi que l'état dans les composants fonctionnels. Actuellement,

Les crochets sont une nouvelle proposition de fonctionnalité qui vous permet d'utiliser l'état et d'autres fonctions de React sans écrire de classe. Ils sont publiés dans React comme une partie de v16.8.0

useEffect peut être utilisé pour répliquer le comportement du cycle de vie. useState peut être utilisé pour stocker l'état dans un composant de fonction.

Syntaxe de base :

useEffect(callbackFunction, [dependentProps]) => cleanupFunction

Vous pouvez mettre en œuvre votre cas d'utilisation dans des crochets tels que

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 peut également renvoyer une fonction qui sera exécutée lorsque le composant sera démonté. Cela peut être utilisé pour se désabonner des auditeurs, en reproduisant le comportement de la fonction componentWillUnmount :

Ex : componentWillUnmount

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

Pour faire useEffect conditionnel à des événements spécifiques, vous pouvez lui fournir un tableau de valeurs pour vérifier les changements :

Ex : componentDidUpdate

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

Crochets équivalents

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

Si vous incluez ce tableau, assurez-vous d'inclure toutes les valeurs de la portée du composant qui changent dans le temps (props, état), ou vous pourriez vous retrouver à référencer des valeurs de rendus précédents.

Il y a quelques subtilités à utiliser useEffect ; consultez l'API Here .


Avant la v16.7.0

La propriété des composants fonctionnels est qu'ils n'ont pas accès aux fonctions du cycle de vie de Reacts ou à l'outil de gestion du cycle de vie. this mot-clé. Vous devez étendre le React.Component si vous souhaitez utiliser la fonction de cycle de vie.

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

Les composants fonctionnels sont utiles lorsque vous souhaitez uniquement assurer le rendu de votre composant sans avoir besoin d'une logique supplémentaire.

1 votes

Comme je l'ai dit, vous avez une logique dans votre composant et votre exigence veut que vous utilisiez une fonction de cycle de vie et vous ne pouvez pas le faire avec des composants fonctionnels. Il est donc préférable d'utiliser des classes. Utilisez un composant fonctionnel lorsque votre composant ne contient pas de logique supplémentaire.

2 votes

Il faut noter que ce n'est pas l'équivalent exact de componentDidUpdate. useEffect(() => { // action here }, [props.counter]) est déclenché lors du rendu initial alors que componentDidUpdate ne l'est pas.

5 votes

passing an empty array as second argument triggers the callback in useEffect only after the initial render Cela ressemble à une façon de construire des choses qui n'est pas très pratique :/ J'espère que l'équipe de réaction proposera quelque chose de mieux dans les prochaines versions.

65voto

Yohann Points 600

Vous pouvez utiliser react-pure-lifecycle pour ajouter des fonctions de cycle de vie aux composants fonctionnels.

Exemple :

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 votes

Qu'est-ce que Grid ? Je ne le vois pas défini quelque part dans votre extrait de code ? Si vous vouliez utiliser redux avec cela aussi, pourriez-vous vous en sortir avec quelque chose comme export default lifecycle(methods)(connect({},{})(ComponentName)) ?

0 votes

@SeanClancy Désolé pour la réponse tardive. L'extrait de code a été mis à jour.

1 votes

Est-ce que cela est considéré comme une bonne pratique ? Devrais-je essayer d'autres solutions avant d'opter pour celle-ci ou puis-je l'utiliser si je la trouve la plus facile ?

9voto

Shivam Points 1242

Première solution : Vous pouvez utiliser le nouveau react HOOKS API. Actuellement en React v16.8.0

Les crochets vous permettent d'utiliser davantage de fonctionnalités de React sans classes. Les crochets fournissent une API plus directe aux concepts React que vous connaissez déjà : props, state, context, refs, et cycle de vie . Hooks résout tous les problèmes abordés avec Recompose.

Une note de l'auteur de recompose (acdlite, 25 octobre 2018) :

Bonjour, j'ai créé Recompose il y a environ trois ans. Environ un an après j'ai rejoint l'équipe React. Aujourd'hui, nous avons annoncé une proposition pour Hooks. Hooks résout tous les problèmes que j'ai tenté de résoudre avec Recompose il y a trois ans, et plus encore. Je vais cesser la maintenance active de ce paquet (à l'exception peut-être de corrections de bogues ou correctifs pour la compatibilité avec les futures versions de React), et recommander aux gens d'utiliser Hooks à la place. Votre code existant avec Recompose fonctionnera toujours, mais ne vous attendez pas à de nouvelles fonctionnalités.

Deuxième solution :

Si vous utilisez une version de react qui ne supporte pas les hooks, pas d'inquiétude, utilisez recompose (Une ceinture utilitaire React pour les composants de fonction et les composants d'ordre supérieur) à la place. Vous pouvez utiliser recompose pour attacher lifecycle hooks, state, handlers etc à un composant de la fonction.

Voici un composant sans rendu qui attache méthodes de gestion du cycle de vie via le cycle de vie HOC (de recomposer).

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

0voto

Chandan Purohit Points 970

Vous pouvez utiliser le module create-react-class. Documentation officielle

Bien sûr, vous devez d'abord l'installer

npm install create-react-class

Voici un exemple de fonctionnement

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

-1voto

Gabriel Ferreira Points 338

Si vous devez utiliser React LifeCycle, vous devez utiliser Class.

Échantillon :

import React, { Component } from 'react';

class Grid extends Component {

 constructor(props){
  super(props)
 }

 componentDidMount () { /* do something */ }

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

}

2 votes

Je ne veux pas utiliser la classe.

3 votes

La question était de savoir comment utiliser les méthodes du cycle de vie avec un composant fonctionnel, et non une classe.

0 votes

Maintenant, avec React Hooks

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X