2015-11-30 20 views
22

I documenti per React indicano che le funzioni del componente sono accessibili da un componente padre tramite i riferimenti. Vedere: https://facebook.github.io/react/tips/expose-component-functions.htmlReact ES6 | Come accedere alle funzioni del componente figlio tramite i riferimenti

Sto tentando di utilizzare questo nella mia applicazione, ma in esecuzione in un errore "non definito non è una funzione" quando viene chiamata la funzione figlio. Mi chiedo se questo abbia qualcosa a che fare con l'utilizzo del formato ES6 per le classi React perché non vedo altre differenze tra il mio codice e i documenti.

Ho un componente Dialog simile al seguente pseudocodice. La finestra di dialogo ha un pulsante "Salva" che chiama save(), che deve chiamare la funzione save() nel componente Contenuto figlio. Il componente Contenuto raccoglie informazioni dai campi del modulo figlio ed esegue il salvataggio.

class MyDialog extends React.Component { 
    save() { 
    this.refs.content.save();     <-- save() is undefined 
    } 

    render() { 
    return (
     <Dialog action={this.save.bind(this)}> 
     <Content ref="content"/> 
     </Dialog>); 
    } 
} 

class Content extends React.Component { 
    save() { 
    // Get values from child fields 
    // and save the content 
    } 
} 

ho potuto invece passare un oggetto di scena (saveOnNextUpdate) fino al contenuto e quindi eseguire salvare ogni volta che è vero, ma io preferirei capire come ottenere il metodo descritto nel documento sopra Reagire al lavoro.

Qualche idea su come ottenere l'approccio del doc per lavorare o accedere alla funzione del componente figlio in modo diverso?

+0

Quale versione di reagire stai usando? – Tyrsius

+0

Il tuo pseudo esempio funziona: https://jsfiddle.net/vbj34euk/ quindi probabilmente è un altro problema. Potresti pubblicare più del codice reale? – m90

+0

Per componente avvolto (un componente collegato a Redux o altri plug-in). dobbiamo usare getWrappedInstance() per ottenere l'istanza avvolta e quindi possiamo accedere allo stato, ai riferimenti e ai metodi di quel componente. Ecco il video che lo spiega - https://youtu.be/VpdKjocgCtA – Prem

risposta

-1

Come si è visto, la M90 aveva ragione: questa era una questione completamente diversa. Sto postando la soluzione nel caso qualcuno si imbattesse nello stesso problema in futuro.

La mia applicazione è compilata con Redux e il problema deriva dall'utilizzo della funzione react-redux connect per connettere un componente allo store/stato globale. Per qualche ragione, esportare un componente e collegarlo al negozio rende impossibile accedere alle funzioni al suo interno. Per ovviare a questo, ho dovuto rimuovere ogni utilizzo dello stato globale dal contenuto in modo che potessi esportarlo come componente "stupido".

Per essere più chiari, Content.js si presentava così:

var connect = require('react-redux').connect; 

class Content extends React.Component { 
    save() { 
    // Get values from child fields 
    // and save the content 

    // Use of this.props.stateObject 
    } 
} 

function mapStateToProps(state) { 
    const { 
    stateObject 
    } = state; 

    return { 
    stateObject 
    }; 
} 

module.exports = connect(mapStateToProps)(Content); 

Rimozione l'uso di stato globale (e quindi l'uso di connessione e mapStateToProps mi ha permesso di esportare il componente utilizzando:

module.exports = Content; 

Accesso alla this.refs.content.save() magicamente funzionato dopo aver fatto questo.

+1

Si potrebbe voler aggiungere questo come un problema per il repository Redux. Sembra qualcosa che potrebbe essere risolto. –

+0

Questo ha senso, in realtà. La funzione connect() di React-Redux crea un nuovo componente wrapper attorno a quello che hai effettivamente scritto tu stesso. Il componente wrapper non ha una funzione save(), quindi quell'approccio non funzionerà. In questo caso è preferibile utilizzare l'approccio pass-down-a-callback. – markerikson

+4

La funzione connect() ha un flag withRef per il terzo parametro, che potrebbe essere la soluzione al tuo problema. Sebbene francamente il fatto che il componente principale chiami un metodo sul suo componente figlio sembra piuttosto anti-Reagire. –

39

Redux connect accetta un parametre un'opzione come parametro via. In questo op parametro di riferimento è possibile impostare il flag withRef su true. Quindi è possibile accedere alle funzioni di refs utilizzando getWrappedInstance(). Come questo:

class MyDialog extends React.Component { 
    save() { 
    this.refs.content.getWrappedInstance().save(); 
    } 

    render() { 
    return (
     <Dialog action={this.save.bind(this)}> 
     <Content ref="content"/> 
     </Dialog>); 
    } 
} 

class Content extends React.Component { 
    save() { ... } 
} 

function mapStateToProps(state) { ... } 

module.exports = connect(mapStateToProps, null, null, { withRef: true })(Content); 

Per saperne di più su di esso qui: https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options

Vale la lettura di questo articolo circa l'uso di arbitri e considerare se ci sono migliori approcci: https://facebook.github.io/react/docs/refs-and-the-dom.html#dont-overuse-refs

+2

stringa ref è deprecato – InspiredJW

+1

Vorrei dare più pollici se potessi. Ore trascorse in cerca di una soluzione. Questo l'ha inchiodato. :) – Rob10e

+0

Funziona. Grazie –

0

Un modo alternativo per farlo sarebbe quello di utilizzare un altro nome dell'elica (diverso da ref). Ho scoperto che questo funziona bene anche se si sta utilizzando una libreria come styled-components o emotion Ad esempio in un collegato MyComponent:

<MyComponent 
    ... 
    innerRef={(node) => { this.myRef = node; }} 
/> 
Problemi correlati