【问题标题】:React Universal pass data to componentReact Universal 将数据传递给组件
【发布时间】:2016-09-13 22:27:35
【问题描述】:

嗨,我是 React 的新手。我正在尝试通过 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
      });
    });
});

// 路由.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>
);

// 客户端.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')
);

// 数据包装器

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>
        );
    }
}

谁能指出我正确的方向,并尽可能解释我做错了什么

谢谢

【问题讨论】:

    标签: reactjs react-router


    【解决方案1】:

    您当前正在渲染DataWrapper 中的孩子,但您没有传递道具。

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

    {this.props.children && React.cloneElement(this.props.children, {
      state: this.state
    })}
    

    【讨论】:

    • 嗯,你是说把这个逻辑放到 HomePage.js 中。
    【解决方案2】:

    在这个用例中,我建议使用 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);
    }
    

    【讨论】:

      猜你喜欢
      • 2018-07-14
      • 2015-01-28
      • 1970-01-01
      • 2016-10-28
      • 1970-01-01
      • 2021-08-20
      • 2016-12-24
      • 2019-05-26
      • 1970-01-01
      相关资源
      最近更新 更多