在反应路由器 v4 中使用 Meteor 服务器渲染的 Meteor.subscribe 函数的类型错误



我正在使用流星的服务器渲染包中用React路由器V4,但我得到了一个typeError,that Meteor.subscribe不是一个函数,我无法弄清楚为什么会发生这种情况或什么是错误的

这是我在客户端上的代码:

import React from 'react';
import { Meteor } from 'meteor/meteor';
import { render } from 'react-dom';
import {RenderRoutes} from '../imports/api/routes.jsx'
import { onPageLoad } from 'meteor/server-render';
import ReactDOM from 'react-dom';
import {
  Router,
  Route,
  Link,
  Switch
 } from 'react-router-dom'
import createBrowserHistory from 'history/createBrowserHistory'
const history = createBrowserHistory()
const Application = () => (
   <Router history={history}>
      <RenderRoutes/>
   </Router>
);
onPageLoad(()=> {
   ReactDOM.render(<Application/>, document.getElementById('react-root'));
});

和在服务器上:

onPageLoad((sink) => {
   const context = {};
   const App = props => (
      <StaticRouter location={props.location} context={context}>
       <RenderRoutes/>
      </StaticRouter>
   );
  sink.renderIntoElementById('app', renderToString(<App location=
   {sink.request.url} />));
  });

我能够使用上述非常简单的应用程序正确地工作,正是订阅和createContainer带来了错误,是否有一种单独的方式来处理它们?

这是我在客户上订阅的方式:

export default createContainer(() => {
  const handle1 = Meteor.subscribe('categories');
  const handle2 = Meteor.subscribe('subcategories');
  const handle3 = Meteor.subscribe('products');
  const isReady1 = handle1.ready()
  const isReady2 = handle2.ready()
  const isReady3 = handle3.ready()
  return {
    products: isReady3 ? Products.find({}).fetch() : [],
    categories: isReady1 ? Categories.find({}).fetch() : [],
    subcats: isReady2 ? SubCategories.find({}).fetch(): [],
  };
 }, B2C);

如果您能弄清楚发生了什么或我犯的错误,那将是很棒的谢谢

删除所有订阅并添加自动发布后,它工作正常,但是我认为这不是一个不当的解决方案,因为我不希望在任何地方发布所有数据?

解决:我将所有订阅都放在Meteor.isclient块中,因此,即使客户端上存在代码,并且一个人将其用于服务器范围,即即使是Meteor.isclient Block,也不应在服务器上运行。为可能导致服务器渲染错误

的代码提供。

另一个解决方案是通过将Meteor.subscribe添加为返回具有ready函数的对象的函数,以返回true

,将服务器端列为nonkey-patch the服务器端。

服务器端:

onPageLoad(sink => {
  const context = {};
  // monkey patching subscribe on the server to be ready immediately
  Meteor.subscribe = (topic) => ({ready: () => true});
  sink.renderIntoElementById("app", renderToString(
    <StaticRouter location={sink.request.url} context={context}>
      <App />
    </StaticRouter>
  ));
});

这样,您就无需单独触摸每个组件。

最新更新