1

我正在使用 React 和hypernova(带有php 绑定)来执行一些 React 组件的服务器端渲染。以下是我的以下测试组件和超新星的响应。

测试.js

import React from 'react';
import { renderReact } from 'hypernova-react';

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

  render() {
    return (
      <p onClick={() => alert('hey')}>click me</p>
    );
  }
}

export default renderReact('Test', Test);

超新星反应

WF\Hypernova\JobResult Object
(
    [error] => 
    [html] => 
        <div data-hypernova-key="Test" data-hypernova-id="e5af0b95-2a31-4ce4-8e36-808605fd4115">
            <p data-reactroot="">click me</p>
        </div>
        <script type="application/json" data-hypernova-key="Test" data-hypernova-id="e5af0b95-2a31-4ce4-8e36-808605fd4115">
            <!--{"prop1":"a","prop2":"b"}-->
        </script>
    [success] => 1
    ...
)

如上图,props都被成功传递了,但是onClickhandler却无处可寻。但是,它肯定存在于转译的代码中。

捆绑.js

// code before and after class omitted for brevity
var Test = function (_React$Component) {
  _inherits(Test, _React$Component);

  function Test(props) {
    _classCallCheck(this, Test);

    return _possibleConstructorReturn(this, (Test.__proto__ || Object.getPrototypeOf(Test)).call(this, props));
  }

  _createClass(Test, [{
    key: 'render',
    value: function render() {
      return _react2.default.createElement(
        'p',
        { onClick: function onClick() {
            return alert('hey');
          } },
        'click me'
      );
    }
  }]);

  return Test;
}(_react2.default.Component);

exports.default = (0, _hypernovaReact.renderReact)('Test', Test);

我能在这个问题上找到的唯一东西是在github 问题跟踪器中,有人在其中抱怨同样的事情,但显然<p>标签上不应该有事件处理程序;它应该存在于 React 交付的代码中。我还尝试使用带/不带箭头符号的类属性分配单击处理程序(在后一种情况下显式绑定在构造函数中)。我在捆绑的 React 代码中添加了一个<script>标签,但这似乎没有什么不同。

这是一个错误,还是我做错了什么?

4

2 回答 2

0

是的,这不足以使组件正常工作。

你做了什么Test.js

...
export default renderReact('Test', Test);

它实际上是您的组件的服务器端渲染Test。因此,当您看到 hypernova 正确返回您时:

<div data-hypernova-key="Test" data-hypernova-id="e5af0b95-2a31-4ce4-8e36-808605fd4115">
  <p data-reactroot="">click me</p>
</div>
<script type="application/json" data-hypernova-key="Test" data-hypernova-id="e5af0b95-2a31-4ce4-8e36-808605fd4115">
  <!--{"prop1":"a","prop2":"b"}-->
</script>

除了这部分,您还需要加载客户端脚本并运行组件的重新水合(https://reactjs.org/docs/react-dom.html#hydra)。在 hypernova 中,您需要准备另一个带有入口点的包:

// Test.js
const Test = () => {...}
export default Test

// index.js
import Test from './Test'

renderReact('Test', Test); // this will call hydrate when loaded in browser directly

index.html并在您的页面上手动加载此捆绑包:

...
<script src='public/bundle.js'></script>

为了帮助提供此文件,hypernova 具有以下配置:

hypernova({
  ...,
  createApplication () {
    const app = express()

    app.get('/', (req, res) => res.status(200).json('OK'))

    app.use('/public', express.static(path.join(process.cwd(), 'public')))

    return app
  }
})

享受!希望它能帮助您弄清楚如何使用超新星。

于 2020-02-11T18:58:29.150 回答
0

事实证明,当使用服务器端渲染时,组件需要同时在服务器端和客户端进行渲染。在我的例子中,这需要创建两个单独的 webpack 配置:一个用于 hypernova 服务器,一个用于客户端 React 代码。然后,我需要添加类似的代码

if (typeof document !== 'undefined') {
  ReactDOM.render(<Test />, document.getElementById('puzzle'));
}

在父组件中,以便 React 将它们呈现在客户端上,而不会在服务器上生成异常。

我从这个问题中弄清楚了这一点。

于 2018-06-08T15:06:01.980 回答