2017-05-18 17 views
0

私はRedux saga boilerplateのフォークを持っており、サーバー側でストアを更新しようとしています。それはうまくいくが、ストアが更新されたときにコンポーネントは更新されない(mapStateToPropsを呼び出さない)。どうしましたか?助けてください。コンポーネントは小道具(React SSR)を受け取りません

Server log

コンポーネントソース:

import React, { Component, PropTypes } from 'react'; 
import { connect } from 'react-redux'; 
import { testAction } from '../../actions'; 

class Event extends Component { 
    static propTypes = { 
    title: PropTypes.string, 
    testAction: PropTypes.func 
    } 
    componentWillMount() { 
    this.props.testAction({ test: 'test' }); 
    } 
    render() { 
    return (
     <div> 
     Event - {this.props.title} 
     </div> 
    ); 
    } 
} 

function mapStateToProps(state) { 
    console.log(state); 
    return { 
    title: state.default.test 
    }; 
} 

export default connect(
    mapStateToProps, 
    { testAction } 
)(Event); 

server.jsソース:一般的に

import Express from 'express'; 
import React from 'react'; 
import ReactDOMServer from 'react-dom/server'; 
import favicon from 'serve-favicon'; 
import compression from 'compression'; 
import http from 'http'; 
import proxy from 'express-http-proxy'; 
import path from 'path'; 
import url from 'url'; 
import { match, createMemoryHistory } from 'react-router'; 

import config from './config'; 
import configureStore from './store/configureStore'; 
import Html from './helpers/Html'; 
import getRoutes from './routes'; 
import waitAll from './sagas/waitAll'; 
import { Root } from 'containers'; 

const app = new Express(); 
const server = new http.Server(app); 

// disable `X-Powered-By` HTTP header 
app.disable('x-powered-by'); 

app.use(compression()); 
app.use(favicon(path.join(__dirname, '..', 'static', 'favicon.ico'))); 
app.use(Express.static(path.join(__dirname, '..', 'static'))); 

// Proxy to API 
app.use('/api', proxy(config.apiBaseUrl, { 
    // eslint-disable-next-line 
    forwardPath: (req, res) => url.parse(req.url).path 
})); 

app.use((req, res) => { 
    if (__DEVELOPMENT__) { 
    webpackIsomorphicTools.refresh(); 
    } 

    const memoryHistory = createMemoryHistory(); 
    const store = configureStore(); 
    const allRoutes = getRoutes(store); 
    const assets = webpackIsomorphicTools.assets(); 

    function hydrateOnClient() { 
    const htmlComponent = <Html assets={assets} store={store} />; 
    const renderedDomString = ReactDOMServer.renderToString(htmlComponent); 
    res.send(`<!doctype html>\n ${renderedDomString}`); 
    } 

    if (__DISABLE_SSR__) { 
    hydrateOnClient(); 
    return; 
    } 

    match({ routes: allRoutes, location: req.url }, (error, redirectLocation, renderProps) => { 
    if (redirectLocation) { 
     res.redirect(redirectLocation.pathname + redirectLocation.search); 
    } else if (error) { 
     console.error('ROUTER ERROR:', error); 
     res.status(500); 
     hydrateOnClient(); 
    } else if (renderProps) { 
     const preloaders = renderProps.components 
     .filter((component) => component && component.preload) 
     .map((component) => component.preload(renderProps.params, req)) 
     .reduce((result, preloader) => result.concat(preloader), []); 

     const runTasks = store.runSaga(waitAll(preloaders)); 

     runTasks.done.then(() => { 
     const rootComponent = (<Root 
      store={store} 
      routes={allRoutes} 
      history={memoryHistory} 
      renderProps={renderProps} 
      type="server" 
     />); 
     const htmlComponent = <Html assets={assets} component={rootComponent} store={store} />; 
     const renderedDomString = ReactDOMServer.renderToString(htmlComponent); 

     global.navigator = { userAgent: req.headers['user-agent'] }; 
     res.status(200).send(`<!doctype html>\n ${renderedDomString}`); 
     }).catch((e) => { 
     console.log(e.stack); 
     }); 

     store.close(); 
    } else { 
     res.status(404).send('Not found'); 
    } 
    }); 
}); 

if (config.port) { 
    server.listen(config.port, (err) => { 
    if (err) { 
     console.error(err); 
    } 
    console.info('==> Open http://%s:%s in a browser to view the app.', config.host, config.port); 
    }); 
} else { 
    console.error('==>  ERROR: No PORT environment variable has been specified'); 
} 

答えて

0

サーバー・サイド・レンダリングを使用している場合、それは非常に簡単でより効果的になります事前に初期状態を収集し、それを単にクライアントの形でライン上に転送することができます。

おおよその基本動作図:いくつかの情報源からデータを得るいくつかの約束関数があります。クライアント上の既に動作しているページからのアドレスが必要な場合は、fetchでサガを起動するだけで、expressがソースからの応答をブロードキャストします。

SSRの場合は、すべての操作の約束の前に直前に約束しておき、シリアル化されたオブジェクトの形式で送信します。例:

Promise.all([ getData1(), getData2() ]).then((initialState) => { 
    const store = createStore(handlers, initialState); 
    // ..... 
    const htmlComponent = <Html assets={assets} component={rootComponent} store={store} />; 
    const renderedDomString = ReactDOMServer.renderToString(htmlComponent); 
}) 

お知らせ:ReactDOMServer.renderToString機能がすでに約束がそうできるようになりますし、データソースへのアピールの任意のシーケンスを実行することをレンダリングファイバー約束非同期のエンジンの到着と反応の将来のバージョンで非同期モードで動作します。

関連する問題