2016-05-26 2 views
38

Nella documentazione React dicono:Perché ref = 'string' è "legacy"?

Reagire supporta anche utilizzando una stringa (invece di un callback) come un puntello rif su qualsiasi componente, anche se questo approccio è in gran parte legato a questo punto.

https://facebook.github.io/react/docs/more-about-refs.html

Prendiamo il seguente esempio:

class Foo extends Component { 
    render() { 
    return <input onClick={() => this.action()} ref={input => this._input = input} />; 
    } 
    action() { 
    console.log(this._input.value); 
    } 
} 

Perché dovrei preferire questo, invece di:

class Foo extends Component { 
    render() { 
    return <input onClick={() => this.action()} ref='input' />; 
    } 
    action() { 
    console.log(this.refs.input.value); 
    } 
} 

?

Sembra molto più semplice e pulito il secondo esempio.
Ci sono rischi che il metodo stringa venga deprecato?


NB: Sto cercando la risposta "ufficiale" per la dichiarazione nella documentazione, non sto chiedendo di preferenze personali e così via.

+1

È forse qualcosa a che fare con questo? https://facebook.github.io/react/blog/2015/02/24/streamlining-react-elements.html#pending-change-the-refs-semantics cioè interrompere la proprietà del ref al di fuori del genitore? Ci sono altri benefici, ma penso che questo fosse il loro ragionamento iniziale forse? – ctrlplusb

+1

Hmm, leggi più qui: https://github.com/facebook/react/issues/3228#issuecomment-75461381 – ctrlplusb

+0

Per inciso ricevo un errore di sfilacciamento con il primo metodo 'La funzione freccia non dovrebbe restituire l'assegnazione. ' – skube

risposta

34

Anche se forse più semplice, la vecchia API refs può diventare difficile in alcuni casi limite, come quando viene utilizzata in un callback. Ogni tipo di analisi statica è anche un dolore con le stringhe. L'API basata sul callback può fare tutto ciò che l'API della stringa può fare e più con un po 'di verbosità aggiunta.

class Repeat extends React.Component { 
    render() { 
    return <ul> { 
     [...Array(+this.props.times)].map((_, i) => { 
     return <li key={i}> { this.props.template(i) } </li> 
     }) 
    } </ul> 
    } 
} 

class Hello extends React.Component { 
    constructor() { 
    super(); 
    this.refDict = {}; 
    } 

    render() { 
    return <Repeat times="3" template={i => <span ref= {el => this.refDict[i] = el}> Hello {i} </span>} /> 
      {/*         ^^^ Try doing this with the string API   */} 
    } 
} 

ulteriore discussione e un po 'più elenco completo dei possibili problemi con l'API basata stringa possono essere trovati da issue #1373, in cui è stato introdotto l'API basata callback. Includerò qui un elenco dalla descrizione del problema:

L'API di riferimento è interrotta è diversi aspetti.

  • È necessario fare riferimento a questo.refs ['myname'] come stringhe da modalità di chiusura del compilatore in modalità avanzata.

  • Non consente la nozione di più proprietari di una singola istanza.

  • Le stringhe dinamiche magiche potenzialmente interrompono le ottimizzazioni nelle macchine virtuali.

  • Deve essere sempre coerente, perché è risolto in modo sincrono. Ciò significa che il batching asincrono del rendering introduce potenziali bug.

  • Attualmente abbiamo un hook per ottenere ref di pari livello in modo che sia possibile fare riferimento a un componente come se fosse un riferimento di contesto. Funziona solo a un livello. Questo rompe la capacità di avvolgere uno di quelli in un incapsulamento.

  • Non può essere digitato staticamente. Devi lanciarlo a qualsiasi uso in lingue come TypeScript.

  • Non c'è modo di collegare il riferimento al "proprietario" corretto in una richiamata invocata da un bambino. <Child renderer={index => <div ref="test">{index}</div>} /> - questo riferimento verrà allegato quando viene emesso il callback, non nel proprietario corrente.


La documentazione chiamano la stringa vecchia API "legacy" per renderlo più chiaro che l'API callback-based è l'approccio preferito, come discusso in this commit e in this PR che sono il in primo luogo quelli che mettono effettivamente queste affermazioni sulla documentazione. Si noti inoltre che alcuni dei commenti implicano che l'api refs basato su stringa potrebbe essere deprecato ad un certo punto.

12

Originariamente scritto da danabramov su https://news.ycombinator.com/edit?id=12093234

  1. arbitri String non sono componibili. Un componente wrapping non può "snoop" su un riferimento a un figlio se ha già un riferimento di stringa esistente. D'altra parte, i ref callback non hanno un singolo proprietario, quindi puoi sempre comporli.
  2. Le stringhe non funzionano con analisi statiche come Flow. Flow non può indovinare la magia che fa il framework per far apparire la stringa ref su this.refs, così come il suo tipo (che potrebbe essere diverso). I riferimenti al callback sono più adatti all'analisi statica.
  3. Il proprietario per una stringa ref è determinato dal componente attualmente in esecuzione. Ciò significa che con un comune schema di "richiamata di rendering" (ad esempio <DataTable renderRow={this.renderRow} />), il componente sbagliato sarà il proprietario della ref (finirà su DataTable invece del componente che definisce renderRow).
  4. String refs force Reagisce per tenere traccia del componente attualmente in esecuzione. Ciò è problematico perché rende lo stato del modulo react e provoca quindi strani errori quando il modulo react viene duplicato nel pacchetto.