为什么Appbase会返回' undefined'在返回正确的项目之前?

时间:2018-03-24 12:09:42

标签: javascript reactjs

我正在玩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;
&#13;
&#13;

2 个答案:

答案 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._idundefined因为在那时,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>