2016-04-13 7 views
5

Sto lavorando a un'implementazione Drag-and-drop (da zero, non utilizzando una libreria DND) e volevo limitare il numero di aggiornamenti non necessari durante il trascinamento.React: il modo migliore per aggiornare se stessi, ma impedire l'aggiornamento dei bambini?

Il trascinamento del "clone" (che di solito è una copia dell'elemento originale, ma può essere un segnaposto arbitrario) si ottiene aggiornando uno stato su un componente contenitore (il "Clonetainer") e utilizzando quello per applicare una trasformazione . Tuttavia, non ha senso aggiornare l'intero sottoalbero durante una mossa, poiché l'unico cambiamento sono le coordinate del contenitore.

Ecco la mia soluzione a questo:

const ClonetainerRenderShield = React.createClass({ 
    shouldComponentUpdate: function (newProps) { 
     return newProps.shouldUpdate; 
    }, 
    render: function() { 
     return this.props.children; // Simple pass-through 
    } 
}); 

const Clonetainer = React.createClass({ 
    componentWillReceiveProps: function (newProps) { 
     // OR in any further properties that may indicate a move, versus a child update 
     this.isMoveEvent = this.props.offset !== newProps.offset; 
    }, 
    render: function() { 
     const style = { transform: `translate(${this.props.offset.left}px,${this.props.offset.top}px)` }; 
     return <div className="clonetainer-div" style={style}> 
      <ClonetainerRenderShield shouldUpdate={ !this.isMoveEvent }> 
       { this.props.children } 
      </ClonetainerRenderShield> 
     </div>; 
    } 
}); 

(non voglio entrare nei dettagli sul resto del sistema DND, se non per dire che gli eventi del mouse da un componente a monte alimentano il parametro offset al Clonetainer.)

la soluzione mi è venuta per fermare l'aggiornamento ha coinvolto determinare se la Clonetainer è stato innescato per aggiornare a causa di un movimento o di qualche altro motivo (e l'impostazione this.isMoveEvent di conseguenza), quindi spessori un componente tra il Clonetainer ed il bambini che consistono in nient'altro che un UpdateComponentUpdate basato su un puntello passato (shouldUpdate).

Questo funziona. L'ho provato in un modo che mostra che si sta aggiornando quando dovrebbe e non si aggiorna quando non dovrebbe, ma sembra un po 'eccessivo avere un componente di shim separato semplicemente per bloccare gli aggiornamenti dal downhill. C'è un modo per indicare che un componente figlio non deve essere aggiornato dal suo stato precedente in render, senza richiedere che il componente figlio includa la propria logica shouldComponentUpdate?

+3

Penso che il tuo approccio sia corretto e il migliore disponibile. Un altro approccio sarebbe quello di manipolare direttamente il nodo DOM per il 'Clonetainer' durante il trascinamento – VonD

risposta

1

Dovresti essere in grado di modificare componentWillReceiveProps in shouldComponentUpdate nel componente Clonetainer e ritagliare l'uomo medio. shouldComponentUpdate accetta due parametri, (object nextProps, object nextState), che è possibile utilizzare per confrontare gli aggiornamenti this.state e this.props. Restituire true causerà un re-rendering.

const Clonetainer = React.createClass({ 
    shouldComponentUpdate: function (nextProps, nextState) { 
     // OR in any further properties that may indicate a move, versus a child update 
     this.props.offset !== nextProps.offset; 
    }, 
    render: function() { 
     const style = { transform: `translate(${this.props.offset.left}px,${this.props.offset.top}px)` }; 
     return <div className="clonetainer-div" style={style}> 
      { this.props.children } 
     </div>; 
    } 
}); 
+0

Ciò non mi permetterebbe di cambiare il posizionamento sul Clonetainer, però, sarebbe? Il problema che avevo era quando la posizione del Clonetainer doveva cambiare (quindi è necessario eseguire il rendering), ma nessuno dei dati contenuti ha (quindi non dovrebbero). Con shouldComponentUpdate, mi aspetterei che tu ottenga "tutto" (shouldComponentUpdate restituisce true e l'intero albero viene rerenderizzato) o "nothing" (shouldComponentUpdate restituisce false e non cambia nulla). – SuperFLEB

Problemi correlati