2016-03-26 7 views
10

react.jsの使用方法を学び、イベントハンドラを使用する際にいくつか問題があります。最終的な質問は次のようなものです:サーバー側のレンダリングを使用し、イベントハンドラをクライアントに自動的に送信することは可能ですか?React.jsサーバサイドのレンダリングとイベントハンドラ

はここに私の例である: 私は、サーバー側をレンダリングし、クライアント

var React = require("react"); 
var DefaultLayout = require("./layout/default"); 

var LikeButton = React.createClass({ 
    getInitialState: function() { 
    return {liked: false}; 
    }, 
    handleClick: function(event) { 
    this.setState({liked: !this.state.liked}); 
    }, 
    render: function() { 
    var text = this.state.liked ? 'like' : 'haven\'t liked'; 
    return (
     <p onClick={this.handleClick}> 
     You {text} this. Click to toggle. 
     </p> 
    ); 
    } 
}); 

var IndexComponent = React.createClass({ 
    render: function(){ 
     return (
      <DefaultLayout title={this.props.name}> 
       <div> 
         <h1>React Test</h1> 
       </div> 

       <div id="testButton"> 
        <LikeButton/> 
       </div> 

       <script type="text/babel" src="/js/react.js"></script> 
      </DefaultLayout> 
     ) 
    } 
}); 

しかし、「ボタンのように」任意の相互作用を持っていないに送信index.jsxを持っています。私はこのコードをクライアントサイドに追加する必要があります。

var LikeButton = React.createClass({ 
    getInitialState: function() { 
    return {liked: false}; 
    }, 
    handleClick: function(event) { 
    this.setState({liked: !this.state.liked}); 
    }, 
    render: function() { 
    var text = this.state.liked ? 'like' : 'haven\'t liked'; 
    return (
     <p onClick={this.handleClick}> 
     You {text} this. Click to toggle. 
     </p> 
    ); 
    } 
}); 

ReactDOM.render(
    <LikeButton />, 
    document.getElementById('testButton') 
); 

私はreact.jsから始めましたが、ここではいくつかの主要な概念が欠落している可能性があります。しかし、なぜreact.jsは、ページサーバー側をレンダリングするときにコードを作成するだけではなく(これをクライアントに手動で追加する必要があります) このように、私は冗長なコードを持っており、これは大きなアプリケーションで混乱するように感じます。 少なくともreact.jsは、2つのLikeButtonを描画せず、作成した1つのサーバー側をクライアント側コンポーネントに「バインド」するほどスマートです。

+0

これはあなたの質問とは無関係ですが、私はあなたがonClickに渡す前にhandleClick関数をバインドすることになっていると信じています。そうしないと正しいコンテキストがありません。 (しかし、なぜthis.setStateを呼び出すときにエラーをスローする必要があるので、ボタンをクリックするとエラーにならないのか分かりません) –

+2

React.createClassを使用する場合、@ktruongバインディングは必要ありません。自動的にバインドされます。 –

+1

@ jeffpc1993これを指摘してくれてありがとう! –

答えて

12

クライアント側のインタラクティブなReactアプリでは、アプリクライアント側もレンダリングする必要があります。通常、このコードはサーバー上で実行するコードと同じで、なので、冗長コードはありません。それはちょうど同じコードです。あなたは、クライアントとサーバーの両方でレンダリングが過度な可能性がありますが、パフォーマンスとSEOの観点からは完璧な意味があるかどうかを自分自身に尋ねるかもしれません。

ReactDOMServer.renderToString(<MyApp foo={bar} />)は、基本的にマークアップで文字列をレンダリングします。そこにはjavascriptや魔法はありません。ちょうど古いHTMLです。ただし、レンダリングされたマークアップには、クライアントで最初に使用されたReact ID属性が多数あり、最初の仮想DOMを生成してイベントを添付します。

サーバーサイドでレンダリングされたマークアップがサーバーに挿入された同じDOM要素で、クライアントでアプリケーションを再度レンダリングすると、Reactはアプリケーション全体を再描画する必要はありません。新しいVirtual DOMツリーを作成し、それを最初のVirtual DOMツリーと比較し、必要な場合は必要なDOM操作を行います。この仮想DOMの概念は、Reactを最初にすばやくするものです。同じプロセスで、アプリケーションで定義したイベントリスナーは、すでにレンダリングされたマークアップにアタッチされます。

これはすべて非常に高速です。また、検索エンジンがクロールし、ユーザーが最初のレンダリングを見るのを待つ必要がなく、ページをレンダリングするのに必要なサーバー側レンダリングページ(Varnishなどを使用してサーバーにキャッシュできる)の利点があります。基本的にjavascriptを無効にしているユーザーのために働く。

+0

あなたの答えをありがとう。 使用する良い記事を知っていますか?Rearn with Varnish? –

21

この動作は、サーバー側のレンダリングが正確であるためです。 まず、クライアント側とサーバー側の両方で同じコードを実行する必要があります。これは、同形アプリケーションと呼ばれるものです。サーバーとクライアントの両方で実行されるもの
したがって、ReactDOM.renderToString(<Component>)を実行すると、HTMLだけが文字列としてレンダリングされます。コンポーネントのレンダリングメソッドが評価され、初期レンダリングに必要なHTMLが生成されます。
クライアントで同じコードを実行すると、反応してHTMLをルックアップし、必要な場所にJSを添付します。 Reactはこのようにスマートです。クライアント側ですべてを再レンダリングしません。コードを評価し、react-idに基づいてコードを添付する場所を指定します。各DOM要素が指定されています。 (反応している要素を調べると反応するでしょう)

同じことを2回レンダリングする利点は何でしょうか?
であり、答えはperceived loading timeである。また、JSを無効にしたユーザーの最小限の表示も可能です。

クライアントレンダリングアプリケーション
は、これは単に、クライアントがアプリケーションの作品をレンダリングする方法です。 JSの(多くの場合、非常に大きなされている)のバンドル、およびデータがフェッチされ、評価され、ユーザーが唯一のすべてのスケルトンHTMLの後にコンテンツが表示されます

client rendered app

(レンダリングされたクライアントは、あまりにもアプリケーションに反応します)。これは、すべてがロードされるまで、しばらくスピンナーやローディング画面を凝視しなければならないことが多いことを意味します。

どのように同形のアプリケーションの動作同形アプリケーション(クライアントとサーバーの両方を実行します)

server rendered app
この場合、サーバはあなたのコンポーネントを評価することによって、フル HTMLを生成します。 HTMLがダウンロードされると直ちにコンテンツが表示されます。 アプリは一度完全に機能するだけですが、JSバンドルもダウンロードされ、評価されます。したがって、JSは両側で実行する必要があります。
したがって、ユーザーは以前よりもはるかに高速にコンテンツを表示します。したがって、知覚される積載時間の大幅な減少。

+7

私は@ dannyjolieの答えに正しいとマークしました。なぜなら、それは私の質問に答えて、以前に投稿されたからです。しかし、まだ私の質問に答える努力に感謝します。それはまた、react.jsがどのように動作し、どのようなコンセプトが続くのかをよりよく理解するのに役立ちました! – Jodo

関連する問題