简体   繁体   English

使用客户端和服务器端呈现来反应同构组件

[英]React isomorphic component with both client-side and server-side rendering

I want to create a react app with both client side and server side rendering. 我想创建一个具有客户端和服务器端呈现的react应用程序。

Here is the example: 这是一个例子:

import styles from './Main.css';

import React, {Component} from 'react';
import Info from './Info/Info';
import Record from './Record/Record'

export default class Main extends Component {
    render() {
        return (
            <div className={styles.main}>
                <div className={styles.mainIn + ' clearfix'}>
                    <div className={styles.mainLeft}>
                        <Info info_num="2012201972"/>
                    </div>
                    <div className={styles.mainRight}>
                        <div className="clearfix mb20">
                            <Record />
                        </div>
                    </div>
                </div>
            </div>
        )
    }
}

In this component Main , it needs to be rendered at the client side except <Record /> 在此组件Main ,除了<Record />之外,它需要在客户端呈现

Component Record 组件Record

import styles from './Record.css';
import layout from '../../shared/styles/layout.css'

import React, {Component} from 'react';

export default class Record extends Component {
    render() {
        return (
            <div className="float_two">
                <div className={layout.box + ' mr10'}>
                    This is Record!
                </div>
            <div>
        )
    }
}

Here is my question: 这是我的问题:

I have searched some examples of server-side rendering examples with ReactDom.renderToString and react-router . 我用ReactDom.renderToStringreact-router搜索了服务器端渲染示例的一些示例。 However, there is no tutorial with both client-side and server-side rendering. 但是,没有客户端和服务器端呈现的教程。

What I want to achieve is that, client first loads and renders Component <Main /> and then loads <Record /> from server-side. 我想要实现的是,客户端首先加载并呈现Component <Main /> ,然后从服务器端加载<Record />

Another question is that, how to load the style module Record.css with renderToString, because I think in this renderToString can just load the html things not the css. 另一个问题是,如何使用renderToString加载样式模块Record.css,因为我认为在这个renderToString中只能加载html而不是css。

When people refer to server-side rendering they are usually referring to the initial rendering of the top-level application at a certain route, not individual components. 当人们提到服务器端渲染时,他们通常指的是某个路径上的顶级应用程序的初始渲染,而不是单个组件。

I'm having trouble understanding your use case is for what you request. 我无法理解您的用例是针对您的要求。 Your React application is one big tree of Fragments , so rendering a single component server-side does not really make sense. 您的React应用程序是Fragments一个大树,因此渲染单个组件服务器端并不真正有意义。 If you want Record to be a part of React then the client will need to know about it, so why not just render it on the client side as per usual? 如果你想让Record成为React的一部分,那么客户端需要了解它,那么为什么不按照惯例在客户端进行渲染呢?

If you really need to render it server side then I guess you could build the Record component so that it does an AJAX request and then the html returned could be rendered using https://facebook.github.io/react/tips/dangerously-set-inner-html.html , but I wouldn't recommend it. 如果你真的需要渲染它的服务器端,那么我猜你可以构建Record组件,以便它执行一个AJAX请求,然后返回的html可以使用https://facebook.github.io/react/tips/dangerously-呈现 - set-inner-html.html ,但我不推荐它。

My guess is that Record requires some kind of data from the server side and that is why you want to render it there? 我的猜测是, Record需要来自服务器端的某种数据,这就是为什么要在那里渲染它? Instead just fetch that data as JSON and use that to render the component client side. 而只是将该数据作为JSON获取并使用它来呈现组件客户端。


Having read your comments, I know what you are trying to do. 读完你的评论后,我知道你要做什么。 What you want is to dynamically load content (not rendered html) from the server in response to some event (scrolldown, button click or whatever). 你想要的是从服务器动态加载内容(不是渲染的html)以响应某些事件(滚动,按钮点击或其他)。 React is very good at this. React非常擅长这个。 By changing the state (ie what Records there are) of your application, React will take care of rerendering efficiently. 通过更改应用程序的状态(即有什么记录),React将有效地处理重新渲染。

This is a very simple application. 这是一个非常简单的应用程序。 It starts by having 2 items (foo and bar) that should be rendered. 它首先要有两个应该渲染的项目(foo和bar)。 In response to an action (button click in this case) more data is loaded into the state and thus rendered to the page. 响应一个动作(在这种情况下按钮点击),更多数据被加载到状态,从而呈现给页面。 All you need to do is modify this so that instead of the setTimeout you do an AJAX call to your backend to get the actual data. 您需要做的就是修改它,以便代替setTimeout对您的后端进行AJAX调用以获取实际数据。

Live version here: https://codepen.io/dpwrussell/pen/qadrko 这里的实时版本: https//codepen.io/dpwrussell/pen/qadrko

class Application extends React.Component {

  constructor(props) {
    super(props);

    // Start with 2 records
    this.state = {
      records: [
        {
          name: 'foo',
          description: 'Some foo'
        },
        {
          name: 'bar',
          description: 'Some bar'
        }
      ]
    };

    // Bind handlers
    this.loadMoreRecords = this.loadMoreRecords.bind(this);
  }

  // Method to call which gets more records on demand
  // Here I just use setTimeout and some static data, but in your case
  // this would be AJAX to get the data from your server where the callback
  // would do the setState. I use a 2 second delay to exaggerate a delay getting
  // the data from the server.
  loadMoreRecords() {
    setTimeout(() => {
      this.setState({
        records: this.state.records.concat([
          {
            name: 'hello',
            description: 'Some newly loaded hello'
          },
          {
            name: 'world',
            description: 'Some newly loaded world'
          }
        ])
      })
    }, 2000);
  }

  // Method to render whatever records are currently in the state
  renderRecords() {
    const { records } = this.state;
    return records.map(record => {
      return (
        <li>{ `${record.name} - ${record.description}` }</li>
      );
    })
  }

  // React's render method
  render() {
    return (
      <div>
        <h1>List of Records Page</h1>
        <ul>
          { this.renderRecords() }
        </ul>
        <input type='button' onClick={this.loadMoreRecords} value='Load more Records' />
      </div>
    );
  }
}

/*
 * Render the above component into the div#app
 */
ReactDOM.render(<Application />, document.getElementById('app'));

Using css-modules-require-hook . 使用css-modules-require-hook It's similar to babel-register but for .css file. 它与babel-register类似,但是对于.css文件。 Basically, it transforms your require('Record.css') to a javascript Object base on your hook config. 基本上,它会将您的require('Record.css')转换为您的hook配置上的javascript Object。 So your hook config should be same as your webpack css-loader config. 所以你的钩子配置应该与你的webpack css-loader配置相同。

Put it in the entry file of your server. 将它放在服务器的入口文件中。

const hook = require('css-modules-require-hook');

hook({/* config */});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM