web-dev-qa-db-fra.com

Appeler une méthode de composant React de l'extérieur

Je souhaite appeler une méthode exposée par un composant React à partir de l'instance d'un élément React.

Par exemple, dans ce fichier jsfiddle https://jsfiddle.net/r6r8cp3z/ je souhaite appeler la méthode alertMessage à partir de la référence HelloElement.

Y a-t-il un moyen d'y parvenir sans avoir à écrire des wrappers supplémentaires?

Edit (code copié de JSFiddle)

<div id="container"></div>
<button onclick="onButtonClick()">Click me!</button>
var onButtonClick = function () {

    //call alertMessage method from the reference of a React Element! Something like HelloElement.alertMessage()
    console.log("clicked!");
}

var Hello = React.createClass({displayName: 'Hello',

    alertMessage: function() {
        alert(this.props.name);                             
    },

    render: function() {
        return React.createElement("div", null, "Hello ", this.props.name);
    }
});

var HelloElement = React.createElement(Hello, {name: "World"});

React.render(
    HelloElement,
    document.getElementById('container')
);
61
user1341217

Il y a deux façons d'accéder à une fonction interne. Un niveau, comme vous le souhaitez, au niveau instance, un autre, niveau statique.

Exemple

Vous devez appeler la fonction sur le retour à partir de React.render. Voir ci-dessous.

Statique

Jetez un coup d’œil à ReactJS Statique . Notez cependant qu'une fonction statique ne peut pas accéder aux données d'instance. this serait donc undefined.

var onButtonClick = function () {
    //call alertMessage method from the reference of a React Element! 
    HelloRendered.alertMessage();
    //call static alertMessage method from the reference of a React Class! 
    Hello.alertMessage();
    console.log("clicked!");
}

var Hello = React.createClass({
    displayName: 'Hello',
    statics: {
        alertMessage: function () {
            alert('static message');
        }
    },
    alertMessage: function () {
        alert(this.props.name);
    },

    render: function () {
        return React.createElement("div", null, "Hello ", this.props.name);
    }
});

var HelloElement = React.createElement(Hello, {
    name: "World"
});

var HelloRendered = React.render(HelloElement, document.getElementById('container'));

Alors faites HelloRendered.alertMessage().

44
Jeff Fairley

J'ai fait quelque chose comme ça:

class Cow extends React.Component {

    constructor (props) {
        super(props)
        this.state = {text: 'hello'}
    }

    componentDidMount () {
        if (this.props.onMounted) {
            this.props.onMounted({
                say: text => this.say(text)
            })
        }
    }

    render () {
        return (
            <pre>
                 ___________________
                < {this.state.text} >
                 -------------------
                        \   ^__^
                         \  (oo)\_______
                            (__)\       )\/\
                                ||----w |
                                ||     ||
            </pre>
        )
    }

    say (text) {
        this.setState({text: text})
    }

}

Et puis ailleurs:

class Pasture extends React.Component {

    render () {
        return (
            <div>
                <Cow onMounted={this.cowMounted.bind(this)} />
                <button onClick={this.changeCow.bind(this)} />
            </div>
        )
    }

    cowMounted (callbacks) {
        this.cowCallbacks = callbacks
    }

    changeCow () {
        this.cowCallbacks.say('moo')
    }

}

Je n’ai pas testé ce code exact, mais c’est un peu la même chose que ce que j’ai fait dans un projet à moi et ça marche très bien :). Bien sûr, ceci est un mauvais exemple, vous devriez simplement utiliser des accessoires pour cela, mais dans mon cas, le sous-composant a effectué un appel d'API que je voulais conserver à l'intérieur de ce composant. Dans ce cas, c'est une solution intéressante.

15
gitaarik

Tu peux faire comme

import React from 'react';

class Header extends React.Component{

    constructor(){
        super();
        window.helloComponent = this;
    }

    alertMessage(){
       console.log("Called from outside");
    }

    render(){

      return (
      <AppBar style={{background:'#000'}}>
        Hello
      </AppBar>
      )
    }
}

export default Header;

Maintenant, en dehors de ce composant, vous pouvez appeler comme ceci ci-dessous

window.helloComponent.alertMessage();
10
Kushal Jain

J'ai deux réponses à cette question:

1- utilisez votre fonction comme une méthode statique:

    statics: {
    alertMessage: function () {
        console.log('Method One');
    }
},

Mais cette méthode a un gros problème, car dans les méthodes statiques, vous n’avez pas accès à this et si vous voulez utiliser this cette méthode ne fonctionne pas, utilisez donc la méthode 2.

2- Premier dans votre class:

constructor(props){
    super(props);
    window.alertMessage = this.alertMessage.bind(this);
}

alertMessage () {
    console.log('Method Two');
}

ensuite, dans chaque composant, vous pouvez utiliser la commande ci-dessous:

4
meisam nazari

Avec la méthode render potentiellement obsolète de la valeur renvoyée, l'approche recommandée consiste maintenant à attacher une référence de rappel à l'élément racine. Comme ça:

ReactDOM.render( <Hello name="World" ref={(element) => {window.helloComponent = element}}/>, document.getElementById('container'));

auquel nous pouvons ensuite accéder en utilisant window.helloComponent, et l’une de ses méthodes est accessible avec window.helloComponent.METHOD.

Voici un exemple complet:

var onButtonClick = function() {
  window.helloComponent.alertMessage();
}

class Hello extends React.Component {
  alertMessage() {
    alert(this.props.name);
  }

  render() {
    return React.createElement("div", null, "Hello ", this.props.name);
  }
};

ReactDOM.render( <Hello name="World" ref={(element) => {window.helloComponent = element}}/>, document.getElementById('container'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container"></div>
<button onclick="onButtonClick()">Click me!</button>

3
Brett DeWoody

Vous pouvez simplement ajouter un gestionnaire onClick au div avec la fonction (onClick est la propre implémentation de Reav de onClick) et vous pouvez accéder à la propriété à l'intérieur de { } accolades et votre message d'alerte apparaîtra.

Si vous souhaitez définir des méthodes statiques pouvant être appelées sur la classe de composant, vous devez utiliser la statique. Bien que:

"Les méthodes définies dans ce bloc sont statiques, ce qui signifie que vous pouvez les exécuter avant la création des occurrences de composant. Elles ne permettent pas d'accéder aux propriétés ni à l'état de vos composants. Si vous souhaitez vérifier la valeur des accessoires dans un fichier statique méthode, demandez à l'appelant de transmettre les accessoires comme argument de la méthode statique. " ( la source )

Quelques exemples de code:

    const Hello = React.createClass({

        /*
            The statics object allows you to define static methods that can be called on the component class. For example:
        */
        statics: {
            customMethod: function(foo) {
              return foo === 'bar';
            }
        },


        alertMessage: function() {
            alert(this.props.name);                             
        },

        render: function () {
            return (
                <div onClick={this.alertMessage}>
                Hello {this.props.name}
                </div>
            );
        }
    });

    React.render(<Hello name={'aworld'} />, document.body);

J'espère que cela vous aide un peu, car je ne sais pas si j'ai bien compris votre question, alors corrigez-moi si je l'ai mal interprétée :)

2
Danillo Felixdaal

Si vous êtes dans ES6, utilisez simplement le mot clé "statique" de votre exemple dans votre méthode: static alertMessage: function() { ...
},
 

L'espoir peut aider n'importe qui là-bas :)

1
darmis

méthode 1using ChildRef:

public childRef: any = React.createRef<Hello>();

public onButtonClick= () => {
    console.log(this.childRef.current); // this will have your child reference
}

<Hello ref = { this.childRef }/>
<button onclick="onButtonClick()">Click me!</button>

Méthode 2:using window register

public onButtonClick= () => {
    console.log(window.yourRef); // this will have your child reference
}

<Hello ref = { (ref) => {window.yourRef = ref} }/>`
<button onclick="onButtonClick()">Click me!</button>
1

Il semble que la statique soit déconseillée et que les autres méthodes permettant d’exposer certaines fonctions avec render semblent compliquées. Pendant ce temps, cette réponse de Stack Overflow sur le débogage de React , bien qu’elle paraisse bidon, a fait le travail pour moi.

1
philipkd
class AppProvider extends Component {
  constructor() {
    super();

    window.alertMessage = this.alertMessage.bind(this);
  }

  alertMessage() {
    console.log('Hello World');
 }
}

Vous pouvez appeler cette méthode à partir de la fenêtre en utilisant window.alertMessage().

0
Mygel Bergstresser