React Universal将数据传递给组件

时间:2016-09-13 22:27:35

标签: reactjs react-router

嗨,我是全新的反应。我试图通过React通用渲染将数据从服务器传递到客户端。但我现在好运。我仍然可以渲染HTML,但我无法通过this.props.data

访问数据

这是我的代码

// server.js

app.get('*', (req, res) => {
  match({
    routes: (<Router>{routes}</Router>),
    location: req.url
  },
    (err, redirect, renderProps) => {
      if (err) {
        return res.status(500).send(err.message);
      } else if (redirect) {
        return res.redirect(302, redirect.pathnam + redirect.search);
      } else if (renderProps.components.some(component => component === NotFoundPage)) {
        res.status(404);
      }

      let data = [
        {
          title: 'Godfather'
        },
        {
          title: 'Godfather 2'
        }
      ];

      data = JSON.stringify(data);
      const renderedApp = renderToString(
        <DataWrapper data={data}>
          <RouterContext {...renderProps} />
        </DataWrapper>
      );

      res.render('index.ejs', {
        renderedApp
      });
    });
});

// routes.js

import React from 'react';
import { Route, IndexRoute } from 'react-router';
import HomePage from './components/routes/HomePage';
import MovieDetailsPage from './components/routes/MovieDetailsPage';
import NotFoundPage from './components/routes/NotFoundPage';
import App from './components/app';

export {
  NotFoundPage
}; 

export default (
  <Route path="/">
    <IndexRoute component={HomePage} />
    <Route path="movie" component={MovieDetailsPage} />
    <Route path="*" component={NotFoundPage} />
  </Route>
);

// client.js

import 'babel-polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, browserHistory } from 'react-router';
import routes from './routes';
import DataWrapper from '../src/DataWrapper';

let data = [];

ReactDOM.render(
  <DataWrapper data={data}>
    <Router history={browserHistory} routes={routes} onUpdate={window.scrollTo(0, 0)}/>
  </DataWrapper>, 
  document.getElementById('app')
);

// DataWrapper

import React, { Component } from 'react';

class DataWrapper extends Component {
  getChildContext () {
    return {
      data: this.props.data
    };
  }

  render () {
    return this.props.children;
  }
}

DataWrapper.childContextTypes = {
  data: React.PropTypes.oneOfType([
    React.PropTypes.object,
    React.PropTypes.array
  ]).isRequired
};

export default DataWrapper;

// HomePage.js我要访问this.props.data

中的数据
import React, { Component } from 'react';

export default class HomePage extends Component {
    constructor(props) {
        super(props);
        this.state = {
            data: this.props.data
        };
    }

    render() {
        return (
            <div>
                <h1>{this.state.data}</h1>
            </div>
        );
    }
}

有人可以指出我正确的方向并尽可能地解释我做错了吗

谢谢

2 个答案:

答案 0 :(得分:0)

您目前正在<style> html{ background-color: gray; } </style> 渲染孩子,但您没有传递道具。

不确定这是否是执行此操作的最佳方式,但这是我如何获得道具和状态传递

DataWrapper

答案 1 :(得分:0)

在这种情况下,我建议使用Redux而不是编写自定义数据包装器。因为 Redux可以使事实成为唯一的来源,无论其处于哪个级别(父级或子级)以及页面的呈现位置(服务器或客户端),所有组件都可以引用。即使引入了更多的开销,它也可以帮助您使架构师更清晰。

这是我之前使用的一些伪代码:

// server.js

// configureStore will create a empty store here.
const store = configureStore();
// Then use store.setState or any middleware to prepopulate the store.
....
const jsx = (
  <ReduxProvider store={store}>
    <StaticRouter context={context} location={req.url}>
      <App/>
    </StaticRouter>
  </ReduxProvider>
);
const html = '<!doctype html><html><head></head>
    <body>
      <script>
        window.REDUX_DATA = ${ JSON.stringify(store.getState()) }
      </script>
      <div id="root">${ReactDOM.renderToString(jsx)}</div>
    </body>
  </html>'
res.send(html)

// client.js

const render = App => {
  // configStore will create store in client side with initial state passed from server.
  const store = configStore(window.REDUX_DATA);
  return ReactDOM.hydrate(
    <ReduxProvider store={store}>
      <BrowserRouter>
          <App/>
      </BrowserRouter>
    </ReduxProvider>,
    document.getElementById('root')
  );
};

// HomePage.js

class HomePage extends React.Component {
  render() {
    return (
      <div>
        this.props.foo.value
      </div>
    )
  }

const mapStateToProps = (state) => ({foo: state.foo});
export default connect(mapStateToProps)(HomePage);
}