我使用React创建了一个简单的Meteor应用程序。它使用下面显示的三个文件(没有其他文件)在名为client
的文件夹中。在控制台中,该应用程序将输出:
withTracker
rendering
withTracker
rendering
props {} {}
state null null
换句话说,App组件呈现两次。输出的最后两行指示this.props
和this.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
更改触发组件重新呈现后才显示该数据。我认为在第一次渲染后设置一个标志就足够了,但是似乎我需要做一些更复杂的事情。
[这是“功能”,它不仅限于流星。这是异步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
希望对您有帮助