我正在玩AppBase.io作为数据库,我不明白为什么这个组件在获得一个项目后呈现两次?好像是AppBase"数据库"之后首先返回 undefined ,然后返回正确的项。有人知道为什么吗?查看示例,我得到2个日志。
在这个组件中,我需要从数据库中获取一个项目并进行渲染(没什么特别的。)
感谢您的解释。
#foobar :nth-child(3) h1::before {
/*your rule*/
}

var appbaseRef = new Appbase({
url: "https://JHtFTzy4H:d083068b-596c-489d-9244-8db2ed316e79@scalr.api.appbase.io",
app: "winwin"
});
class ItemFull extends React.Component {
constructor() {
super();
this.state = {
item: ''
}
}
componentWillMount() {
appbaseRef.get({
type: "items",
id: 'AWI5K7Q-5Q83Zq9GZnED'
}).on('data', (response) => {
this.setState({
item: response
});
}).on('error', function(error) {
console.log(error)
})
}
render() {
console.log(this.state.item._id, '<-- console_log');
return (<div></div>);
}
}
ReactDOM.render(<ItemFull /> , document.getElementById('root'));
&#13;
答案 0 :(得分:1)
那是因为appbaseRef.get
是异步的。 ItemFull
执行初始渲染,您会看到第一个console.log
this.state.item._id
第一次实际检查字符串对象(“”)中的_id
,这当然是未定义的。
然后在this.setState
中调用componentWillMount
(已经挂载并呈现至少一次)并更新状态强制组件因状态更改而重新呈现。
这就是你看到2个控制台日志的原因。
您无法阻止render()
挂钩执行,但您可以确保仅在数据到达时呈现您的内容:
render() {
console.log(this.state.item._id, '<-- console_log');
if(this.state.item) { // this will check if item is different than ''
return (
<div>
</div>
)
}
}
还有一件事。使用componentDidMount
进行初始数据提取,因为它是建议的位置。
答案 1 :(得分:1)
没有。您在componentWillMount
中启动的异步调用不会阻止呈现过程(这很好),因此在调用完成之前调用render
,因此this.state.item._id
为undefined
因为在那时,this.state.item
是''
(您在构造函数中设置的值)。
这是完全正常的,只需确保以适当的方式呈现组件,因为它还没有信息,例如:
var appbaseRef = new Appbase({
url: "https://JHtFTzy4H:d083068b-596c-489d-9244-8db2ed316e79@scalr.api.appbase.io",
app: "winwin"
});
class ItemFull extends React.Component {
constructor() {
super();
this.state = {
item: ''
}
}
componentWillMount() {
appbaseRef.get({
type: "items",
id: 'AWI5K7Q-5Q83Zq9GZnED'
}).on('data', (response) => {
this.setState({
item: response
});
}).on('error', function(error) {
console.log(error)
})
}
render() {
return <div>{this.state.item._id ? this.state.item._id : "loading..."}</div>;
}
}
ReactDOM.render(<ItemFull />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/appbase-js/2.2.11/appbase.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
如果在获得该信息之前根本不应该呈现该组件,那么您在错误的位置请求它。 :-)你在父组件中请求它,只有当你有信息(传递props
中的信息)时才呈现这个组件,如下所示:
var appbaseRef = new Appbase({
url: "https://JHtFTzy4H:d083068b-596c-489d-9244-8db2ed316e79@scalr.api.appbase.io",
app: "winwin"
});
class ParentComponent extends React.Component {
constructor(...args) {
super(...args);
this.state = {item: null};
}
componentWillMount() {
appbaseRef.get({
type: "items",
id: 'AWI5K7Q-5Q83Zq9GZnED'
}).on('data', (response) => {
this.setState({
item: response
});
}).on('error', function(error) {
console.log(error)
})
}
render() {
return this.state.item ? <ItemFull item={this.state.item} /> : <div>loading...</div>;
}
}
class ItemFull extends React.Component {
render() {
return <div>{this.props.item._id}</div>;
}
}
ReactDOM.render( <ParentComponent /> , document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/appbase-js/2.2.11/appbase.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>