React state 似乎没有在渲染之前获取 api 和设置状态

React state doesn't seem to be fetching api and setting state before render

我正在尝试获取 api 个引号并用第一个引号填充反应组件。稍后我将使用按钮随机选择一个。我刚刚在学习 React,我在 freecodecamp 中的 React 教程没有显示任何关于 fetch 的内容,所以我找到了在线提取这些引号的代码。如果我在 this.setState 之后添加另一个回调,我可以 console.log 并查看所有数组,但即使在渲染中使用 if 语句,它似乎也没有处于渲染状态。在状态设置为数组后,我缺少关于设置状态或让组件呈现的内容。这个我已经看过了 .

class Quotes extends React.Component{
  constructor(props){
    super(props)
    this.state = {
      quotes: []
    }
  }
  
  componentDidMount() {
      fetch("https://type.fit/api/quotes")
      .then((response) => response.json())
      .then(quotesList => {
          this.setState({ quotes: quotesList });
      });
  }
  
  render(){ 
    if (!this.state.quotes) {
            return <div />
        }
    
    return(
      <div>
        <p id="text">{this.state.quotes[0].text}</p>
        <p id="author">{this.state.quotes[0].author}</p>
        <div id="buttons">
          <button id="new-quote">New Quote</button>
          <a id="tweet-quote" href="#"><i className="fa-brands fa-twitter"></i></a>
        </div>
      </div>
    );
  }
}

class QuoteBox extends React.Component{
  constructor(props){
    super(props)
  }
  
  render(){
    return(
      <div id="quote-box">
         <Quotes />
      </div>
      
    );
  } 
}

ReactDOM.render(<QuoteBox />, document.getElementById('page-wrapper'))
#page-wrapper{
  
  #quote-box{
    display:flex;
    height:100vh;
    justify-content:center;
    align-items:center;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="page-wrapper">
  
</div>

空数组 [] 不是虚假值,因此您的 if 不会被触发并且数组访问越界。在你的 if 中检查数组长度,它会起作用。

请参阅 Whosebug 上的 this thread,其中涵盖了真实值和虚假值。

此处将 if 中的条件更改为 this.state.quotes.length === 0.

class Quotes extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      quotes: [],
    };
  }

  componentDidMount() {
    fetch("https://type.fit/api/quotes")
      .then((response) => response.json())
      .then((quotesList) => {
        this.setState({ quotes: quotesList });
      });
  }

  render() {
    // check for array length here
    if (this.state.quotes.length === 0) {
      return <div>Fetching data...</div>;
    }

    return (
      <div>
        <p id="text">{this.state.quotes[0].text}</p>
        <p id="author">{this.state.quotes[0].author}</p>
        <div id="buttons">
          <button id="new-quote">New Quote</button>
          <a id="tweet-quote" href="#">
            <i className="fa-brands fa-twitter"></i>
          </a>
        </div>
      </div>
    );
  }
}

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

  render() {
    return (
      <div id="quote-box">
        <Quotes />
      </div>
    );
  }
}

ReactDOM.render(<QuoteBox />, document.getElementById("page-wrapper"));
#page-wrapper{
  
  #quote-box{
    display:flex;
    height:100vh;
    justify-content:center;
    align-items:center;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="page-wrapper">
  
</div>