流星和withTracker:为什么一个组件渲染两次?

问题描述 投票:2回答:1

我使用React创建了一个简单的Meteor应用程序。它使用下面显示的三个文件(没有其他文件)在名为client的文件夹中。在控制台中,该应用程序将输出:

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

换句话说,App组件呈现两次。输出的最后两行指示this.propsthis.state在渲染之间均未更改。

index.html

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

main.jsx

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

import App from './App.jsx'

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

App.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的任何组件将always渲染两次吗?

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

meteor meteor-tracker
1个回答
0
投票

[这是“功能”,它不仅限于流星。这是异步javascript的功能。无论您的服务器有多快,来自数据库的数据都会在延迟后到达。

您的页面将立即呈现,然后在数据到达时再次呈现。您的代码需要考虑到这一点。

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

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组件将永远只用数据呈现,因此它可以将prop用于初始状态,并且可以将PropTypes设置为isRequired

希望对您有帮助

© www.soinside.com 2019 - 2024. All rights reserved.