7

私の問題

最初にサーバー側でコンポーネントをレンダリングし、次にブラウザ側で 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 コンポーネントに同期する方法はありますか?

ありがとう!

4

1 に答える 1

6

これは興味深い質問です!大まかに言うと、問題は、チェックボックスをクリックしたときに最上位コンポーネントにバブルアップした「変更」イベントを React がキャッチしていないことです。これは、クライアント側でまだインスタンス化されていないためです。ハーフソリューションは、への呼び出しを手動でシミュレートすることでこれを処理しonChangeます。onChange イベントをキューに入れる必要があるのではないかと考え始めましたが、React には必要なものがすべて揃っていることに気付きました。

「4分の3」の解決策は、単に名前syncStateFromDOMcomponentDidMountに変更することであり、手動で呼び出す必要さえありません。ドキュメントによると、React の最新バージョンでcomponentDidMountは、ブラウザでのみ呼び出され、コンポーネントがマウントされた後 (つまり、React.render返されようとしているとき) のライフサイクル コールバックです。ユースケースに最適な場所です。参照: http://jsfiddle.net/qdt4z3w9/

これにより、コンポーネント自体の外部にあるコードの問題が解決されます! ただし、元のレンダリングが行われた後も状態設定が行われています。残念ながら、これが基本的に React の仕組みだと思います。既存の DOM ノードを参照に一致させるには、まず各コンポーネントを完全にマウントする必要があります。しかし、追加の仮想 DOM 差分は、非常に高速になるように設計されているため、わずかな代償で済みます。

お役に立てれば!

于 2014-12-16T07:02:29.303 に答える