组件在渲染之前不会等待API响应

时间:2019-05-31 16:33:12

标签: reactjs

我尝试了在API调用之后设置标志的条件渲染,并且也使用componentDidMount,但是无法使该组件在渲染之前等待API响应。我知道API响应是有效的,因为它在控制台中正常记录。我是新来的反应者,您能告诉我我做错了什么吗?我看过关于Stackoverflow的类似问题,但找不到解决方法。非常感谢!

我从代码片段中删除了一些方法,以使其更具可读性。

import { OTSession, OTPublisher, OTStreams, OTSubscriber } from 'opentok-react';

import {
  SAMPLE_SERVER_BASE_URL,
} from './config';

export default class CallPane extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      error: null,
      connection: 'Connecting',
      publishVideo: true,
      apiKey: '',
      sessionId: '',
      token: '',
      isLoaded: false,
    };

  componentDidMount() {
    fetch(SAMPLE_SERVER_BASE_URL + '/session')
      .then(data => data.json())
      .then(data => {
        console.log(data)
        this.setState({ apiKey: data.apiKey })
        console.log(data.apiKey)
        this.setState({ sessionId: data.sessionId })
        console.log(data.sessionId)
        this.setState({ token: data.token })
        console.log(data.token)
        this.setState({ isLoaded: true })
      })
      .catch((err) => {
        console.error('Failed to get session credentials', err);
        alert('Failed to get opentok sessionId and token. Make sure you have updated the config.js file.');
      });
  }

  render() {

    const { error, connection, publishVideo } = this.state;
    // const { apiKey, sessionId, token } = this.state;

    return (
      // (isLoaded) 
      <div>
        <div id="sessionStatus">Session Status: {connection}</div>
        {error ? (
          <div className="error">
            <strong>Error:</strong> {error}
          </div>
        ) : null}
        <OTSession
          apiKey={this.apiKey}
          sessionId={this.sessionId}
          token={this.token}
          onError={this.onSessionError}
          eventHandlers={this.sessionEventHandlers}
        >
          <button id="videoButton" onClick={this.toggleVideo}>
            {publishVideo ? 'Disable' : 'Enable'} Video
          </button>
          <OTPublisher
            properties={{ publishVideo, width: 250, height: 250, }}
            onPublish={this.onPublish}
            onError={this.onPublishError}
            eventHandlers={this.publisherEventHandlers}
          />
          <OTStreams>
            <OTSubscriber
              properties={{ width: 300, height: 300 }}
              onSubscribe={this.onSubscribe}
              onError={this.onSubscribeError}
              eventHandlers={this.subscriberEventHandlers}
            />
          </OTStreams>
        </OTSession>
      </div>
    );
  }
}

2 个答案:

答案 0 :(得分:1)

您可以将if语句放入渲染方法中

render() {

    const { error, connection, publishVideo, isLoaded } = this.state;
    // const { apiKey, sessionId, token } = this.state;

    if(!isLoaded) {
      // not loaded
      return (
        <div>Loading...</div>
      )
    }

    return (
      // (isLoaded) 
      // your code
    );
  }

答案 1 :(得分:0)

您可以使用简单的if语句检查资源是否已准备就绪。如果不是,请渲染加载栏或类似内容。来自react documentation

class ExampleComponent extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      externalData: null,
    };
  }

  componentWillMount() {
    fetch(SAMPLE_SERVER_BASE_URL + '/session')
      .then(data => data.json())
      .then(data => {
        this.setState({ externalData: data });
      });
  }

  render() {
    if (this.state.externalData === null) {
      // Render loading state ...
    } else {
      // Render real UI ...
    }
  }
}

您还可以使用如下所示的内容来确保始终呈现另一个组件。

class ExampleComponent extends  React.Component {

  constructor(props) {
    super(props);

    this.state = {
      externalData: null,
    };
  }

  componentWillMount() {
    fetch(SAMPLE_SERVER_BASE_URL + '/session')
      .then(data => data.json())
      .then(data => {
        this.setState({ externalData: data });
      });
  }

  //This render is begin called even before props getting updated
  render() {
      return (
          <div>
          <h1>{'This will always render yay '}</h1>
          { this.state && this.state.externalData &&
              <div>{'This will just render after the return of the async call'}</div>
          }
          </div>
      )
  }
}