2016-06-11 14 views
3

Frage außen reagieren:reactjs - aussetzen reagieren Komponentenmethoden Baum

Wie kann ich aussetzen eine Komponente Methoden an anderen Orten reagieren?

Zum Beispiel möchte ich React-Router this.context.router.push (Standort) von einem Element außerhalb von React aufrufen.

Vielleicht könnte ich eine React-Komponente-Methode zum Fensterobjekt hinzufügen, so dass es von jedem generischen DOM-Event-Listener oder sogar der Konsole aufgerufen werden kann?

Hintergrund/Use Case:

Ich möchte jQuery Tables in meinem Reagieren App verwenden, da es viele Plugins und Konfiguration zur Verfügung, die im Ökosystem reagieren noch nicht verfügbar sind.

Ich begann von einer vorhandenen React Datentabelle Komponente (Implementierung unten).

Das Original bietet eine nette Option, um eine Renderfunktion zu übergeben, die beispielsweise andere React-Komponenten innerhalb der Zellen rendern kann. Im Folgenden werden die Zellen in der Spalte "Produktname" als React-Router < Link /> Komponenten gerendert.

const data = [ 
     { 
      product_id: '5001', 
      product_price: '$5', 
      product_name: 'Apple' 
     }, 
     ... 
     ]; 

    const renderUrl = 
     (val, row) => { 
     return (<Link to={`/product/${row.product_id}`}>{row.product_name}</Link>); 
     }; 

    const columns = [ 
     { title: 'Product Name', prop: 'product_id', render: renderUrl }, 
     { title: 'Price', prop: 'product_price' }, 
     ]; 

    <DataTable 
     className="datatable-container" 
     columns={columns} 
     initialData={data} 
    /> 

Was ich die vorhandene Komponente ändern getan beinhaltet die Tabelle versteckt von React DOM diffing Algorithmus, da es sonst brechen, wenn jQuery Tables den DOM modifiziert.

  1. Bewegen Sie die Komponente render() Code in eine benutzerdefinierte Methode getDtMarkup() von der Klasse (außerhalb des Lebenszyklus reagieren).
  2. Render() gibt nun eine leere div mit einem ref und ID

    render() { 
        return (
         <div> 
         <div ref="dtContainer" id="dtContainer"></div> 
         </div> 
        ); 
        } 
    
  3. componentDidMount ReactDomServer.renderToStaticMarkup verwendet eine in Klar Reagieren Komponente zu drehen, nicht reagieren Markup und hängt dies auf den # dtContainer div von render(). Schließlich initialisiert jQuery DataTables die gerenderte Tabelle html als fancy 'jQuery DataTable'.

    componentDidMount() { 
    
        let table = this.getDTMarkup(); 
        let dtContainer = this.refs.dtContainer; 
        let renderedTable = ReactDOMServer.renderToStaticMarkup(table, dtContainer); 
    
        $('#dtContainer').append(renderedTable); 
    
        let jqueryTable = $('#dt'); // hard coded in getDTMarkup() for now 
    
        // Turn html table into a jQuery DataTable with desired config options 
        jqueryTable.DataTable({ 
        dom: '<"html5buttons"B>lTfgitp', 
        buttons: [ 
         'copy', 'csv', 'excel', 'pdf', 'print' 
        ], 
        "pagingType": 'numbers', 
        "bAutoWidth": false, 
        "bDestroy": true, 
        "fnDrawCallback": function() { 
         console.log('datatables fnDrawCallback'); 
        } 
        }); 
    } 
    

src https://github.com/alecperkey/react-jquery-datatables/blob/master/src/Table.js#L89-L111

Die Einschränkung, dass ich diese Frage hat, ist, dass ich jetzt nicht in der Lage bin zu verwenden Komponenten reagieren wie <-Link /> innerhalb dieses statischen, nicht -React Markup. Ich benutze < a href = ""> für jetzt, aber dies wird die Seite neu laden, die langsamer ist und den weißen Blitz des Browsers verursacht.

Antwort

-1

Es gibt mehr Möglichkeiten bis verdrahten Komponenten reagieren mit der „äußeren Anwendung“

Sie können wie Methoden als Requisiten zu Ihrer Komponente zu übergeben:

const foo = function(){ 
    alert(1) 
} 

class HelloWorldComponent extends React.Component { 
    render() { 
    return (  
     <h1 onClick={(e) => this.props.cb()}>Hello {this.props.name}</h1>  
    ); 
    } 
} 

React.render(
    <HelloWorldComponent cb={foo} name="Joe Schmoe"/>, 
    document.getElementById('react_example') 
); 

http://jsbin.com/zujebirusa/1/edit?js,output

Mit globalen Methoden angebracht ans Fenster. Denken Sie daran, dass es schwer zu pflegen ist, da es den globalen Namensraum verschmutzen wird.

window.foo = function(){ 
    alert(1) 
} 

class HelloWorldComponent extends React.Component { 
    render() { 
    return (  
     <h1 onClick={(e) => window.foo()}>Hello {this.props.name}</h1>  
    ); 
    } 
} 

React.render(
    <HelloWorldComponent name="Joe Schmoe"/>, 
    document.getElementById('react_example') 
); 

http://jsbin.com/woyokasano/1/edit?js,output

Ihr Code-Basis sauber zu halten mit getrennten Bereiche Mit ES6 Modulsystem, um

//methods.js 

export function foo() { 
    alert(1) 
} 

import {foo} from './methods'; 
class HelloWorldComponent extends React.Component { 
    render() { 
    return (  
     <h1 onClick={(e) => foo()}>Hello {this.props.name}</h1>  
    ); 
    } 
} 

React.render(
    <HelloWorldComponent name="Joe Schmoe"/>, 
    document.getElementById('react_example') 
); 
+3

Sie haben mir gezeigt, wie ein Verfahren zu einer Reaktion Komponente hinzuzufügen. Das ist aber nicht das, was ich zu fragen versuche. Ich versuche, eine React-Komponente vorhandenen Methode an einen globalen Kontext wie Fenster oder ein nicht reagierendes DOM-Element zu binden. ... so kann es von einem generischen DOM-Event-Listener oder sogar der Konsole aufgerufen werden. Zum Beispiel, wie würde ich die React-Router-Funktionalität this.context.router.push an Fensterobjekt binden, so dass mein nicht Reagieren DOM-Element diese Funktion verwenden kann? – AlecPerkey