簡體   English   中英

與Redux和Router進行反應 - 服務器渲染

[英]React with Redux and Router - server rendering

我正在嘗試使用異步調用使服務器呈現工作。 我的問題是,在渲染之前沒有下載數據。

我的代碼(也可以在github上找到: https//github.com/tomekbuszewski/server-rendering

server.js

require('babel-register');

import express from 'express';
import path from 'path';

import React from 'react';
import { renderToString } from 'react-dom/server';
import { Provider } from 'react-redux';
import { getState } from 'redux';
import { match, RouterContext } from 'react-router'

import routes from './app/routes';
import store from './app/store';

const app = express();
const port         = 666;

app.get('/', (req, res) => {
  match({ routes, location: req.url }, (error, redirectLocation, renderProps) => {
    if (renderProps) {
      console.log(renderProps.components);
      res.send(renderToString(
        <Provider store={store}>
          <RouterContext {...renderProps} />
        </Provider>
      ))
    } else {
      console.log('err')
    }
  });
});

app.use('/public', express.static(path.join(__dirname, 'public')));
app.use('/data', express.static(path.join(__dirname, 'data')));

app.listen(port);
console.log(`localhost:${port}`);

routes.js

import React from 'react';
import { Router, Route, browserHistory } from 'react-router';

import App from './Components/App';

const routes = (
  <Router history={browserHistory}>
    <Route path="/" component={App} />
  </Router>
);

export default routes;

App組件具有獲取功能:

const fetch = (dispatch) => {
    const endpoint = '/data/index.json';

    axios.get(endpoint).then((res) => {
        Array.prototype.forEach.call(res.data, d => {
            const payload = {
                id:    d.id,
                title: d.title
            };

            dispatch({type: 'ADD_CONTENT', payload});
        });
    });
};

調度'ADD_CONTENT'動作:

case 'ADD_CONTENT':
  return { ...state, data: [...state.data, action.payload] };

所有工作都很棒客戶端。

  1. 您的redux操作應返回在商店正確加載數據時滿足的承諾

例如:

const fetch = (dispatch) => {
    const endpoint = '/data/index.json';

    return axios.get(endpoint).then((res) => {
        Array.prototype.forEach.call(res.data, d => {
            const payload = {
                id:    d.id,
                title: d.title
            };

            dispatch({type: 'ADD_CONTENT', payload});
        });
    });
};
  1. 您必須使用像redux-connect這樣的包裝器,在加載組件之前調用這些操作。

在您的示例中,路由組件是App

在這種情況下,您將使用所需的redux操作來裝飾該組件,該操作將預加載數據。

import { asyncConnect } from 'redux-connect';

@asyncConnect([{
    promise: ({ store: { dispatch } }) => {
        // `fetch` is your redux action returning a promise
        return dispatch(fetch());
    }
}])
@connect(
    state => ({
        // At this point, you can access your redux data as the
        // fetch will have finished 
        data: state.myReducer.data
    })
)
export default class App extends Component {
    // ...the `data` prop here is preloaded even on the server
}

如果您不使用頂部容器中的數據,@ @connect可以裝飾嵌套組件,因為商店在應用程序范圍內可用,但@asyncConnect必須裝飾由react-router直接調用的組件,它不能使用(到目前為止) )在渲染樹中的嵌套組件上,或者在初始渲染期間不會解析它們

因為組件樹的呈現在服務器上只發生一次,所以組件本身不能調用該函數,需要加載之前調用它, 通過 redux-connect和支持promises的redux動作,例如使用redux-thunk中間件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM