2015-02-15 7 views
11

Quando si utilizza React per eseguire il rendering dei componenti sul server, noto che gli attributi data-reactid sono effettivamente casuali. Capisco che è previsto. (https://groups.google.com/forum/#!topic/reactjs/ewTN-WOP1w8)Reattivo stabile per il rendering lato server

Tuttavia è un po 'sorprendente che questo quadro altrimenti funzionale introduca tale non determinismo nell'output della vista. Significa che i rendering successivi di una vista con stato identico creeranno HTML diversi, impedendo, ad esempio, al motore di visualizzazione di restituire un '304 non modificato' o di generare un ETag affidabile. (Apprezzo che tale memorizzazione nella cache possa essere gestita anche a un livello infrastrutturale superiore.)

C'è un modo per inizializzare la generazione dell'identificatore in modo che i reattidi siano deterministici? O è la ragione che è una cattiva idea spiegata da qualche altra parte?

risposta

2

Nel commento finale sulla Google Group thread Ben Alpert dice:

Per il rendering del server, è importante che le diverse componenti resi non hanno gli ID in collisione (anche se sono resi su server diversi, per esempio) quindi li selezioniamo a caso.

+1

Oltre a dire "è importante", non è chiaro perché sia ​​così. –

+1

Ho letto il suo commento dicendo che la ragione per cui React usa gli ID casuali è perché i componenti non possono avere identificatori in collisione, anche su server diversi. Si parla di cambiare [come vengono creati gli ID casuali su Github] (https://github.com/facebook/react/issues/2584) e si potrebbe seguire il loro esempio per generare i propri ID se lo si desidera. –

1

Anche di recente pensato su di esso (appena iniziato a utilizzare reactjs),

Possibile soluzione è abbastanza semplice - non v'è alcun obbligo per ETag deve essere generato da vero html ... - può essere generata da dati visualizzati.

modo da poter generare da dom virtuale - basta usare React.renderComponentToStaticMarkup(…) e generare ETag da esso ...

oppure è possibile rimuovere tutti i reactid di da HTML reso con regexp prima di hashing (probabilmente più veloce quindi il rendering separato). ..

Nel caso in cui si utilizza espresso, questo sarebbe qualcosa di simile:

var virtualDom = React.createFactory(Handler)({}); 
var html = React.renderToString(virtualDom); 

var etag = app.get('etag fn'); 
if (etag) { 
    etag = etag(React.renderComponentToStaticMarkup(virtualDom), 'utf8'); 
    etag && res.set('ETag', etag); 
} 

res.render(...); 
0

questo mi è stato bugging troppo, così ho fatto un po 'scavare per vedere cosa sarebbe successo se ho fatto la radice reactid deterministico .

È possibile sovrascriverlo in React 0.14.x se si è disposti a tollerare il seguente trucco. Nel file sul lato server in cui si chiama ReactDOM.renderToString, collocare questo nella parte superiore:

// Override the ServerReactRootIndex.createReactRootIndex function 
var ServerReactRootIndex = require('react/lib/ServerReactRootIndex'); 
ServerReactRootIndex.createReactRootIndex = function(){ 
    return "x"; // Results in an attribute like data-reactid=".x" 
}; 

// Use React as usual 
// NB: require('react') must come AFTER overriding ServerReactRootIndex.createReactRootIndex 
var React = require('react'); 

Questo non fa parte delle API Reagire, quindi questo potrebbe rompersi in un prossimo futuro. Tuttavia, questo funziona per ora se ne hai assolutamente bisogno. Rende anche l'attributo checksum data-react stabile per lo stesso DOM renderizzato.

Se nella pagina sono presenti più componenti di root React, questi devono avere ID di root diversi, quindi è necessario modificare questa funzione per tener conto di ciò.