Meteor 使用React Router V4从createContainer升级到withTracker

Meteor 使用React Router V4从createContainer升级到withTracker,meteor,Meteor,我升级了meteor,并开始收到createContainer()的弃用警告。因此,我尝试用tracker实现,,但是现在我得到了组件(…):必须返回有效的React元素(或null)。您可能返回了未定义、数组或其他无效对象。。我不确定我遗漏了什么,有人能指出我的错误吗 路径:App.jsx import { Meteor } from 'meteor/meteor'; import React from 'react'; import PropTypes from 'prop-types';

我升级了meteor,并开始收到createContainer()的弃用警告。因此,我尝试用tracker实现
,但是现在我得到了
组件(…):必须返回有效的React元素(或null)。您可能返回了未定义、数组或其他无效对象。
。我不确定我遗漏了什么,有人能指出我的错误吗

路径:
App.jsx

import { Meteor } from 'meteor/meteor';
import React from 'react';
import PropTypes from 'prop-types';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { withTracker } from 'meteor/react-meteor-data';

// IsCandidate Spefic Routes
import TestContainer from '../../containers/candidate/TestContainer';

const App = appProps => (
  <Router>
    <ScrollToTop>
      <div className="bgColor">
        <NavBar {...appProps} />
        <Grid className="main-page-container">
          <Switch>
            {/* candidate routes */}
            <IsCandidate exact path="/candidate/testpage/:id" component={withTracker(TestContainer)} {...appProps} />

            {/* IsPublic routes */}
            <Route render={function () {
              return <p>Page not found</p>;
            }}
            />
          </Switch>
        </Grid>
      </div>
    </ScrollToTop>
  </Router>
);

App.propTypes = {
  loggingIn: PropTypes.bool,
  isCandidate: PropTypes.bool
};

export default createContainer(() => {
  const loggingIn = Meteor.loggingIn();
  return {
    loggingIn,
    isCandidate: !loggingIn && !!Meteor.userId() && !!Roles.userIsInRole(Meteor.userId(), 'isCandidate'),
  };
}, App);
import React from 'react';
import PropTypes from 'prop-types'; // ES6
import { Route, Redirect } from 'react-router-dom';

const IsCandidate = ({ loggingIn, isCandidate, component: Component, ...rest }) => (
  <Route
    {...rest}
    render={(props) => {
      if (loggingIn) return <div />;
      return isCandidate ?
      (<Component loggingIn={loggingIn} isCandidate={isCandidate} {...rest} {...props} />) :
      (<Redirect to="/login" />);
    }}
  />
);

IsCandidate.propTypes = {
  loggingIn: PropTypes.bool,
  isCandidate: PropTypes.bool,
  component: PropTypes.func
};

export default IsCandidate;
import { Meteor } from 'meteor/meteor';
import { withTracker } from 'meteor/react-meteor-data';
import { Test } from '../../../api/test/test';

import TestPage from '../../pages/candidate/TestPage';

export default TestContainer = withTracker(({ match }) => {

  const testHandle = Meteor.subscribe('test', match.params.id);
  const loadingTest = !testHandle.ready();
  const testCollection = Test.findOne(match.params.id);
  const testExist = !loadingTest && !!testCollection;


return {
  loadingTest,
  testExist,
  testCollection: testExist ? testCollection : {}
};

}, TestPage);
路径:
Testcontainer.jsx

import { Meteor } from 'meteor/meteor';
import React from 'react';
import PropTypes from 'prop-types';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { withTracker } from 'meteor/react-meteor-data';

// IsCandidate Spefic Routes
import TestContainer from '../../containers/candidate/TestContainer';

const App = appProps => (
  <Router>
    <ScrollToTop>
      <div className="bgColor">
        <NavBar {...appProps} />
        <Grid className="main-page-container">
          <Switch>
            {/* candidate routes */}
            <IsCandidate exact path="/candidate/testpage/:id" component={withTracker(TestContainer)} {...appProps} />

            {/* IsPublic routes */}
            <Route render={function () {
              return <p>Page not found</p>;
            }}
            />
          </Switch>
        </Grid>
      </div>
    </ScrollToTop>
  </Router>
);

App.propTypes = {
  loggingIn: PropTypes.bool,
  isCandidate: PropTypes.bool
};

export default createContainer(() => {
  const loggingIn = Meteor.loggingIn();
  return {
    loggingIn,
    isCandidate: !loggingIn && !!Meteor.userId() && !!Roles.userIsInRole(Meteor.userId(), 'isCandidate'),
  };
}, App);
import React from 'react';
import PropTypes from 'prop-types'; // ES6
import { Route, Redirect } from 'react-router-dom';

const IsCandidate = ({ loggingIn, isCandidate, component: Component, ...rest }) => (
  <Route
    {...rest}
    render={(props) => {
      if (loggingIn) return <div />;
      return isCandidate ?
      (<Component loggingIn={loggingIn} isCandidate={isCandidate} {...rest} {...props} />) :
      (<Redirect to="/login" />);
    }}
  />
);

IsCandidate.propTypes = {
  loggingIn: PropTypes.bool,
  isCandidate: PropTypes.bool,
  component: PropTypes.func
};

export default IsCandidate;
import { Meteor } from 'meteor/meteor';
import { withTracker } from 'meteor/react-meteor-data';
import { Test } from '../../../api/test/test';

import TestPage from '../../pages/candidate/TestPage';

export default TestContainer = withTracker(({ match }) => {

  const testHandle = Meteor.subscribe('test', match.params.id);
  const loadingTest = !testHandle.ready();
  const testCollection = Test.findOne(match.params.id);
  const testExist = !loadingTest && !!testCollection;


return {
  loadingTest,
  testExist,
  testCollection: testExist ? testCollection : {}
};

}, TestPage);
更新

export default withTracker(() => {
  const loggingIn = Meteor.loggingIn();
  return {
    loggingIn,
    isCandidate: !loggingIn && !!Meteor.userId() && !!Roles.userIsInRole(Meteor.userId(), 'isCandidate'),
    isEmployer: !loggingIn && !!Meteor.userId() && !!Roles.userIsInRole(Meteor.userId(), 'isEmployer'),
    isAdmin: !loggingIn && !!Meteor.userId() && !!Roles.userIsInRole(Meteor.userId(), 'isAdmin')
  };
})(App);

App.jsx
中,使用跟踪器导入,但使用
createContainer

withTracker
只接受一个参数(您的被动函数)并包装您的子组件,其中
createContainer
接受两个参数(函数和组件)

编辑 从此行中删除
withTracker
调用App.js:

<IsCandidate exact path="/candidate/testpage/:id" component={withTracker(TestContainer)} {...appProps} />

所以它变成了

<IsCandidate exact path="/candidate/testpage/:id" component={TestContainer} {...appProps} />


怎么样?

当我将
导出默认createContainer(()=>{
更改为
导出默认withTracker(()=>{
时,我仍然得到
组件(…):一个有效的React元素(或null)必须返回
仔细阅读我的答案,不仅要更改容器的导入,还要更改容器的实现。你不能简单地将
createContainer
withTracker
交换。你的解释很有道理,我很感激,但是,我仍然被这个问题难倒。我已经做了更新(见上文)但我没有遵循我所缺少的。我已经阅读了很多次meteor文档,据我所知,我是按照他们建议的方式来做的。你能告诉我我在这里缺少了什么吗。在代码方面,我仍然是个傻瓜。更新了我的答案。请注意,你还在App.js中使用
createContainer
,而不是导入它。