【问题标题】:React/Hypernova - Missing Event HandlersReact/Hypernova - 缺少事件处理程序
【发布时间】:2018-06-07 16:06:25
【问题描述】:

我正在使用 React 和 hypernova(与 php bindings)来执行一些 React 组件的服务器端渲染。以下是我的以下测试组件和 hypernova 的响应。

Test.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 正在成功传递,但找不到 onClick 处理程序。但是,它肯定存在于转译的代码中。

bundle.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 issue tracker 中,有人抱怨同样的事情,但显然&lt;p&gt; 标签上不应该有事件处理程序;它应该存在于 React 交付的代码中。我还尝试使用带/不带箭头符号的类属性分配单击处理程序(在后一种情况下显式绑定在构造函数中)。我在捆绑的 React 代码中添加了一个 &lt;script&gt; 标签,但这似乎没有什么不同。

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

【问题讨论】:

    标签: javascript reactjs webpack babeljs hypernova


    【解决方案1】:

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

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

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

    我从this question 发现了这一点。

    【讨论】:

      【解决方案2】:

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

      你在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#hydrate)。在 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
        }
      })
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-01-25
        • 1970-01-01
        • 1970-01-01
        • 2015-04-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多