3

我使用 React 创建了一个简单的 Meteor 应用程序。它使用名为client. 在控制台中,应用程序打印出:

withTracker
rendering
withTracker
rendering
props {} {}
state null null

换句话说,App 组件被渲染了两次。最后两行输出表明渲染之间既没有this.props也没有变化。this.state

索引.html

<body>
  <div id="react-target"></div>
</body>

主.jsx

import React from 'react'
import { render } from 'react-dom'

import App from './App.jsx'

Meteor.startup(() => {
  render(<App/>, document.getElementById('react-target'));
})

应用程序.jsx

import React from 'react'
import { withTracker } from 'meteor/react-meteor-data'

class App extends React.Component {
  render() {
    console.log("rendering")
    return "Rendered"
  }

  componentDidUpdate(prevProps, prevState) {
    console.log("props", prevProps, this.props)
    console.log("state", prevState, this.state)
  }
}

export default withTracker(() => {
  console.log("withTracker")
})(App)

如果我将 App.jsx 更改为以下内容(删除withTracker包装器),则应用程序仅打印rendering到控制台,并且只执行一次。

import React from 'react'
import { withTracker } from 'meteor/react-meteor-data'

export default class App extends React.Component {
  render() {
    console.log("rendering")
    return "Rendered"
  }

  componentDidUpdate(prevProps, prevState) {
    console.log(prevProps, this.props)
    console.log(prevState, this.state)
  }
}

withTracker什么触发了第二次渲染?由于我无法阻止它的发生,我可以确定任何使用的组件总是withTracker会渲染两次吗?

上下文:在我的实际项目中,我使用withTracker从 MongoDB 集合中读取数据,但我希望我的组件仅在props更改触发组件重新呈现后才显示该数据。我认为在第一次渲染后设置一个标志就足够了,但似乎我需要做一些更复杂的事情。

4

2 回答 2

0

这是一个“功能”,它不仅限于 Meteor。这是异步 javascript 的一个特性。无论您的服务器有多快,来自数据库的数据都会延迟到达。

您的页面将立即呈现,然后在数据到达时再次呈现。您的代码需要允许这样做。

实现此目的的一种方法是使用中间组件(它可以显示“正在加载”,直到数据到达)。假设您有一个名为 的组件List,它将显示来自名为的 mongo 集合中的数据MyThings

const Loading = (props) => {
  if (props.loading) return <div>Loading...</div>
  return <List {...props}></List>
}

export default withTracker((props) => {
  const subsHandle = Meteor.subscribe('all.myThings')
  return {
    items: MyThings.find({}).fetch(),
    loading: !subsHandle.ready(),
  }
})(Loading)

这也意味着你的List组件只会用数据渲染,所以它可以使用道具作为初始状态,你可以设置PropTypesisRequired

我希望这会有所帮助

于 2020-06-06T12:59:45.577 回答
0

不确定您是否遇到了我发现的相同错误,或者这只是其他答案所建议的您在这里遇到的标准 React 行为,但是:

在Meteor0.2.x上运行旧版( 考虑以下:react-meteor-data2.0props

// ./main.js
const withSomethingCount = (C) => (props) => <C { ...props } count={ ... } />
const withPagination = (C) => (props) => <C { ...props } pagination={ ... } />
const withSomething = withTracker((props) => {
  console.log('withSomething:', props);
});

// Assume we're rending a "Hello, World" component here.
export const SomeComponent = withSomethingCount(withPagination(withSomething(...)));

// Console
withSomething: { count: 0 }
withSomething: { count: 0, pagination: { ... } }  
withSomething: { count: 0 }
withSomething: { count: 0, pagination: { ... } }  

无论出于何种原因,我不仅看到了 N 个渲染调用,而且还看到了 N 个渲染调用,它们以重复的方式丢失了属性。对于那些阅读本文并想知道的人,组件只有一种用途,withTrackerHoC 也只有一种用途,父 HoC 没有逻辑会导致 props 的条件传递。

不幸的是,我还没有发现这个错误的根本原因。然而,创建一个新的 Meteor 应用程序并移动代码是唯一可以消除该错误的解决方案。2.0Meteor 应用程序 ( to 2.1) 和依赖项的就地更新并没有解决问题......但是全新安装和运行 agit mv client imports server确实解决了我的问题。

很遗憾,我不得不将其归结为某种形式的漂移,因为在两年的开发过程中随后的 Meteor 更新。

于 2021-03-30T14:36:44.563 回答