How to use React.js to render server-side template

2020-07-10 06:30发布

问题:

I am trying to build an isomorphing app with Sails.js and React. Client-side part is easy. But I run into problems with server-side rendering.

When I try to server-render an *.jsx file with React, I got this:

renderToString(): You must pass a valid ReactElement

I am using sailsjs, react and sails-hook-babel (for ES6 syntax).

./assets/components/Auth.jsx:

import React from 'react';

export class Auth extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <div className='auth'>
        Very simple element without any logic just for test server-rendering.
      </div>
    );
  }
}

./api/controllers/AuthController.js:

var Auth = require('./../../assets/components/Auth.jsx');
import React from 'react';

module.exports = {
    render: function (req, res) {
    //var markup = React.renderToString(
    //  Auth
    //); // This throws an error

    console.log(Auth); // {__esModule: true, Auth: [Function: Auth]}

    //res.view("layout", {app: markup});
  }
};

I have tried both ES5/ES6 syntax everywhere. Error occurs everytime. At clientside this Auth.jsx works fine (I am using webpack with babel-loader).

回答1:

Your problem isn't with your component itself, it's how you're exporting it from your module.

When using just export you need to import your module like this.

import {Auth} from 'auth';

Just using export allows for exporting more than 1 thing from your module.

// My Module.
export function a(x) {
    console.log('a');
}

export function b(x, y) {
    console.log('b');
}

import { a, b } from 'myModule';

or you can use import * from 'myModule'; This is called a named export.

What your use case begs for is the use of export default which allows a single object to be exported from your module.

export default class Auth extends React.Component {}

Thus letting you import your module as a single object without curly braces.

import Auth from 'auth';

Then you need to render using either use JSX syntax React.renderToString(<Auth />); or React.createElement(Auth);

You can read all on how modules in ECMA Script 6 works here