Reactjs 组件在呈现之前不会等待API响应

Reactjs 组件在呈现之前不会等待API响应,reactjs,Reactjs,我尝试过在API调用后设置标志并使用componentDidMount进行条件呈现,但无法让该组件在呈现之前等待API响应。我知道API响应是有效的,因为它在控制台中记录为ok。我是新手,你能告诉我我做错了什么吗?我已经研究了Stackoverflow上的类似问题,但找不到解决方法。非常感谢 我已经从代码片段中删除了一些方法,以使其更具可读性 import { OTSession, OTPublisher, OTStreams, OTSubscriber } from 'opentok-reac

我尝试过在API调用后设置标志并使用componentDidMount进行条件呈现,但无法让该组件在呈现之前等待API响应。我知道API响应是有效的,因为它在控制台中记录为ok。我是新手,你能告诉我我做错了什么吗?我已经研究了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>
    );
  }
}
从“opentok react”导入{OTSession、OTPublisher、OTStreams、OTSubscriber};
进口{
示例\u服务器\u基础\u URL,
}从“./config”开始;
导出默认类CallPane扩展React.Component{
建造师(道具){
超级(道具);
此.state={
错误:null,
连接:'正在连接',
publishVideo:没错,
apiKey:“”,
会话ID:“”,
令牌:“”,
isLoaded:false,
};
componentDidMount(){
获取(示例\u服务器\u基础\u URL+'/session')
.then(data=>data.json())
。然后(数据=>{
console.log(数据)
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((错误)=>{
console.error('获取会话凭据失败',err);
警报('未能获取opentok会话ID和令牌。请确保已更新config.js文件');
});
}
render(){
const{error,connection,publishVideo}=this.state;
//const{apiKey,sessionId,token}=this.state;
返回(
//(已加载)
会话状态:{connection}
{错误(
错误:{Error}
):null}
{publishVideo?'Disable':'Enable'}视频
);
}
}

您可以将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
    );
  }
render(){
const{error,connection,publishVideo,isLoaded}=this.state;
//const{apiKey,sessionId,token}=this.state;
如果(!已加载){
//未加载
返回(
加载。。。
)
}
返回(
//(已加载)
//你的代码
);
}

您可以使用一个简单的if语句,检查资源是否已准备就绪。如果未准备就绪,则呈现加载条或类似内容。从:

您还可以使用类似于以下的方法,以确保始终渲染另一个组件

class ExampleComponent extends  React.Component {

  constructor(props) {
    super(props);

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

  componentDidMount() {
    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>
      )
  }
}
class ExampleComponent扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
外部数据:null,
};
}
componentDidMount(){
获取(示例\u服务器\u基础\u URL+'/session')
.then(data=>data.json())
。然后(数据=>{
this.setState({externalData:data});
});
}
//即使在道具更新之前,也会开始调用此渲染
render(){
返回(
{'这将始终呈现yay'}
{this.state&&this.state.externalData&&
{'这将在异步调用返回后立即呈现'}
}
)
}
}

欢迎使用SO!首先,请注意,通过在传递给setState的对象中包含多个属性,您可以一次设置多个状态变量。但更重要的是,您在何处使用isLoaded?您设置了isLoaded,但注释了我认为您要使用它的行。假设这只是为了测试,请签出,但特别是首先,检查您的
错误
条件与您的
已加载
条件之间的差异。很棒-设置状态对象的优点。感谢@HammerN'Songs。现在阅读文档。感谢@Tom Scholz,组件现在正在正确渲染!由于某种原因,来自的道具没有传递到OTSession component和我得到“ReferenceError:OT未定义”。这可能与状态有关,因为API响应有效,并且可以将其正确记录在与呈现函数相同的范围内。我似乎无法在此注释中添加多行代码。您可以创建一个JSFIDLE或codesandbox来重现问题吗?现在排序好了,谢谢欧-是我的错,只是我试图访问属性的方式!
class ExampleComponent extends  React.Component {

  constructor(props) {
    super(props);

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

  componentDidMount() {
    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>
      )
  }
}