2016-03-21 14 views
0

私はコンポーネントを反応させるデータを渡すことができ豆をしました:のようにサーバー側でそれらをレンダリングする際のデータとコンポーネントをレンダリングする方法

app.get('/', function (req, res, next) { 
    var reactHtml = ReactDOMServer.renderToString(component({data})); 
    res.render('index.jade', {reactOutput: reactHtml}); 
}); 

今私がしましたchangetそれに

server.js:

app.get('*', (req, res) => { 
    // match the routes to the url 
    match({ routes: routes, location: req.url }, (err, redirect, props) => { 
     props.data = {q:123}; 
     const appHtml = ReactDOMServer.renderToString(routerContext(props)); 
     res.render('index.jade', {reactOutput: appHtml}); 
    }) 
}); 

ルーターのコンテキスト

module.exports = React.createClass({ 
    render: function(){return(<RouterContext {...this.props} />)} 
}); 

とルート

module.exports = (
    <Route path="/" component={App} {...this.props}> 
     <IndexRoute component={List}/> 
     <Route path="/about" component={About}/> 
    </Route> 
); 

App.jsx

var App = React.createClass({ 
    render: function() { 
     console.log(this.props); 
     return (
      <div id="app-root" className="container"> 
       <Nav/> 
       <h1>{this.props.q}</h1> 
       {this.props.children} 
       <div className="Row"> 
        <div className="footer col-lg-12"></div> 
       </div> 
      </div> 
     ) 
    } 

}); 

だから、例えば私は私のアプリのコンポーネントで、この時点props.data = {q:123};からデータを取得行いたいが、私はアプリケーションコンポーネントでconsole.log(this.data);を行う際の方法をレンダリングI歴史、場所などがありますが、私のデータはありません。とにかくデータ{q:123}をserver.jsロジックのコンポーネント(AppまたはListまたはAbout)の小道具に渡すことはありますか?

あなたはあなたのデータをシリアル化し、initialStateとして、あなたのルートコンポーネントにそれを渡した場合、たとえば、レンダリングサーバ上のページに追加する必要があり

答えて

0

あなたprops.data = {q:123};は、どこにも呼び出されません。あなたはmatchに渡すコールバック関数へ

3引数は次のとおりです。

  1. エラー:エラーが発生した場合はJavaScript Errorオブジェクト、undefinedそう。
  2. redirectLocation:Locationオブジェクト経路がリダイレクトである場合、 undefinedさもなければ
  3. renderProps:ルートが一致した場合は、ルーティングコンテキストに渡すべき小道具、undefined さもなければ。

    3つのパラメータがすべてundefinedの場合、これは指定された場所に一致するルートが見つかりませんでした。

は、あなたがあなたをレンダリングするために渡されているすべてのコンポーネントを示すだろう、ここで

match({ routes: routes, location: req.url }, (err, redirect, props) => { 
     console.dir(props); 
     const appHtml = ReactDOMServer.renderToString(routerContext(props)); 
     res.render('index.jade', {reactOutput: appHtml}); 
    }) 
}); 

そしてconsole.dir(props.components) console.dirを追加することができますメカニズムを理解するために。あなたもここで新しい反応する要素を作成し、アプリのコンポーネントにデータを渡すにはprops.components

にそれをプッシュすることができていない店舗

データを取得する能力を持っていると、ダミーを作成するには、この関数を変更して

routes.jsx新しいデータを持つコンポーネント

module.exports = function(serverData){ 
    var Dummy= React.createClass({ 
    render: function() { 
     return (
     <div> customProps=serverData </div> 
      );} 
     }); 

    return(
    <Route path="/" component={App}> 
     <Route path='data' component={{PonyMan: Dummy}} 
     <IndexRoute component={List}/> 
     <Route path="/about" component={About}/> 
    </Route> 
    ); 
} 

server.jsx:

app.get('*', (req, res) => { 
    myCustomData = 'I like ponies' 
    const routes = createRoutes(myCustomData); //from imported routes.jsx 
    match({ routes: routes, location: req.url }, (err, redirect, props) => { 
     const appHtml = ReactDOMServer.renderToString(routerContext(props)); 
     res.render('index.jade', {reactOutput: appHtml}); 
    }) 
}); 

App.js

var App = React.createClass({ 
    render: function() { 
     return (
      <div id="app-root" className="container"> 
       <Nav/> 
       <h1>{this.props.main}</h1>//this now shows <div>I Like Ponies</div> 

       //this can still display other routes 
       {this.props.children} 
       <div className="Row"> 
        <div className="footer col-lg-12"></div> 
       </div> 
      </div> 
     ) 
    }  
}); 

P.S.それは私が前に反応するルートをなかったものを例として https://github.com/choonkending/react-webpack-node

+0

ありがとうございました。私はデモをチェックした。それは私が必要とするものを正確に行うように見えます。私は情報源を読むために数時間を費やさなければならない。実際に私は反応ルートのソースを読んでフォークするパスを見つけ、RouterContextのgetChildContext関数を修正して、子コンテキストに追加データを転送させました。しかし、あなたのやり方はもっと納得のいくものになっています。 – xander27

+0

いや、これはもっと「ハック」だと思うでしょう。動的コンテンツにreduxストアのようなものを使用するのは本当に簡単です。初期サーバーをレンダリングしたい場合は、[this](https://github.com/choonkending/react-webpack-node/blob/master/app/api/fetchComponentDataBeforeRender.js)のようなものを追加して、約束を解決することができますレンダリングする前にカスタムデータ用に、あなたはまだすべてのSEOのプロを取得する – PijusV

2

(我々は常に今のところ、いくつかのデータをロードasumeしてみましょう):

だから、
renderInitialState() { 
    const innerHtml = `window.__INITIAL_STATE__ = ${JSON.stringify(this.props.initialState)}`; 
    return <script dangerouslySetInnerHTML={{__html: innerHtml}} />; 
} 

:あなたが「シェル」をレンダリングする代わりに反応するようにヒスイを使用しているように見えること

<script>window.__INITIAL_STATE__ = JSON.stringify(yourObject);</script> 

注意。同じことが適用されますが、ヒスイのテンプレートのためにそれを行います。

通常は、<body>の下に(ただし、アプリのjsスクリプトの上に)レンダリングします。

お客様のクライアントの状態にフラックスを使用している場合は、店舗の作成時にこのオブジェクトを渡します。 Reduxのために:RouterContextはそれをどうするかわからないため

const store = configureStore(window.__INITIAL_STATE__); 
+0

私が使用したヒスイをレンダリングするサーバ側と反応して、ルータの再来特急マングースプロジェクトの良い例を見てReduxの店に チェックこのプロジェクトを使用した方法で容易になるだろう。私はあなたの意見をunderestandが、それはブラウザで実行する必要が含まれているので、それはサーバー間のレンダリング(SEOフレンドリーなど)の賛否論を却下するように見えます。 jade + reactを使用したとき、私はサーバー側でデータのフルページをレンダリングしていました。それは私が反応ルータ(と翡翠なし)で今何をしようとしているのです。 – xander27

+0

実際、私の悪い - 私は間違った質問の名前を書いています。だから今すぐ変更してください。 – xander27

+0

アイデアは、サーバー上でレンダリングし、2番目のレンダリングが同じクライアント上で起こるように必要なデータを渡すことです。すべての同形アプリはデータ/ストアを依然としてクライアントに渡す必要があります - https://github.com/DominicTobias/universal-react/をご覧ください。 –

関連する問題