私の問題
最初にサーバー側でコンポーネントをレンダリングし、次にブラウザ側で React のインテリジェントな再レンダリングを利用する、ReactでIsomorphic Application を構築しています。
React が最初にブラウザー側でレンダリングできるようになる前に、DOM が React コンポーネントの状態と同期しなくなる可能性がある状況に遭遇しました。これは、ユーザーのインターネット接続が低速で、react.js
ファイルのダウンロードに時間がかかる場合に発生する可能性があります(これが、Isomorphic Application を構築している理由でもあります)。
例
これが起こっていることを示すために私がまとめた例です:http://jsfiddle.net/jesstelford/z4o44esb
- この例を実行します
- チェックボックスを切り替えます
- 「Render React」をクリック
- 現在の React の状態がコンソールに出力されます
- まだ { done: false } に設定されていることに注意してください。これは正しくありません
var TodoItem = React.createClass({
// ...
render: function() {
return (
<label>
<input type="checkbox" defaultChecked={this.state.done} onChange={this.onChange} />
{this.props.name}
</label>
);
}
});
// User toggles checkbox ON here, before React is rendered browser-side
// render using React browser-side
var renderedComponent = React.render(component, document.getElementById('content'));
// Incorrectly outputs { done: false }
console.log('React state:', renderedComponent.state);
可能な(半分の)解決策
私は次を使用して1つの可能な解決策を見つけましたReact refs
: http://jsfiddle.net/jesstelford/z4o44esb/2
var TodoItem = React.createClass({
// ...
syncStateFromDOM: function() {
this.setDone(this.refs.done.getDOMNode().checked);
},
render: function() {
return (
<label>
<input ref="done" type="checkbox" defaultChecked={this.state.done} onChange={this.onChange} />
{this.props.name}
</label>
);
}
});
// User toggles checkbox ON here, before React is rendered browser-side
// render using React browser-side
var renderedComponent = React.render(component, document.getElementById('content'));
// Sync state from the DOM
renderedComponent.syncStateFromDOM()
// Correctly outputs { done: true }
console.log('React state:', renderedComponent.state);
このアプローチの欠点は次のとおりです。
- DOM がレンダリングされた後に状態が同期される
- 最初のレンダリングで同期するには、コンポーネント自体の外部に追加のコードが必要です
私の質問
React コンポーネントをサーバー側で事前レンダリングする場合、React がブラウザー側で読み込まれる前にユーザーが DOM を操作した場合、ブラウザー側でレンダリングする前に DOM の状態をその React コンポーネントに同期する方法はありますか?
ありがとう!