简体   繁体   English

React/Hypernova - 缺少事件处理程序

[英]React/Hypernova - Missing Event Handlers

I am using React and hypernova (with php bindings ) in order to perform server-side rendering of some React components.我正在使用 React 和hypernova (带有php 绑定)来执行一些 React 组件的服务器端渲染。 Below is my following test component and the response from hypernova.以下是我的以下测试组件和超新星的响应。

Test.js测试.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);

hypernova response超新星反应

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
    ...
)

As shown above, props are being successfully passed, but the onClick handler is nowhere to be found.如上所示, props成功传递,但onClick处理程序无处可寻。 However, it definitely exists in the transpiled code.但是,它肯定存在于转译的代码中。

bundle.js包.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);

The only thing I've been able to find on the issue has been in the github issue tracker in which someone complains about the same thing, but apparently there isn't supposed to be an event handler on the <p> tag;我唯一能在这个问题上找到的东西是在github 问题跟踪器中,有人抱怨同样的事情,但显然<p>标签上不应该有事件处理程序; it is supposed to exist in code delivered by React.它应该存在于 React 交付的代码中。 I have also tried assigning a click handler using a class property with/without arrow notation (explicitly binding in the constructor in the latter case).我还尝试使用带/不带箭头符号的类属性分配点击处理程序(在后一种情况下在构造函数中显式绑定)。 I have added a <script> tag with my bundled React code, but that doesn't appear to make a difference.我在捆绑的 React 代码中添加了一个<script>标签,但这似乎没有什么区别。

Is this a bug, or am I doing something wrong?这是一个错误,还是我做错了什么?

It turns out that, when using server side rendering, the component needs to be rendered both on the server and on the client.事实证明,在使用服务器端渲染时,组件需要在服务器和客户端上都进行渲染。 In my case, this required creating two separate webpack configs: one for the hypernova server and one for the client React code.就我而言,这需要创建两个单独的 webpack 配置:一个用于 hypernova 服务器,另一个用于客户端 React 代码。 Then, I needed to add code like然后,我需要添加像

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

In the parent components so that React would render them on the client and not generate exceptions on the server.在父组件中,以便 React 将它们呈现在客户端上,而不会在服务器上生成异常。

I figured this out from this question .我从这个问题中弄清楚了这一点

Yeah, this is not enough to make the component properly working.是的,这不足以使组件正常工作。

What you did in Test.js :你在Test.js做了Test.js

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

it's actually a server-side rendering of your component Test .它实际上是您的组件Test的服务器端呈现。 So as you see hypernova returns you correctly:所以当你看到超新星正确返回你时:

<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>

Apart from this part you need to load client script and run re-hydration of your component ( https://reactjs.org/docs/react-dom.html#hydrate ).除了这部分之外,您还需要加载客户端脚本并运行组件的重新水化( https://reactjs.org/docs/react-dom.html#hydrate )。 In hypernova you need to prepare another bundle with entrypoint:在 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

and load this bundle on your index.html page manually:并在您的index.html页面上手动加载此包:

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

to help to serve this file, hypernova has in configuration:为了帮助提供此文件,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
  }
})

Enjoy!享受! Hope it will help you to figure out how to use hypernova.希望它能帮助你弄清楚如何使用超新星。

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

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