React组件未通过状态更新重新渲染

时间:2020-02-04 04:53:17

标签: javascript reactjs

即使我可以确认状态正在更新,我也有一些React组件无法更新的问题。

链接到Codepen在这里:https://codepen.io/paalpwmd/full/WNveejG

  constructor(props){
    super(props)
    this.state = {
    }   
  }


  render(){
      return(
        <div>
          <a href="https://twitter.com/intent/tweet" id="tweet-quote">Tweet me</a>
        </div>
      )
    }
}

class QuoteBody extends React.Component{
  constructor(props){
    super(props)
    this.refreshQuote = this.refreshQuote.bind(this);
    this.state = { quote: "", author: "", quotePos: 0 };
  } 


refreshQuote() {
    let n = Math.floor(Math.random() * (120 - 0 + 1) + 0);
    this.setState({
    quotePos: n
    });
  console.log(this.state.quotePos)
  }

  render(){
    return(
      <div>
      <button id="new-quote" onClick={this.refreshQuote}>New Quote!</button>
      <div id="text"> 
      <p>{this.state.quote}</p>
        </div>
            <div id="author">
        <p>{"- " + this.state.author}</p>
        </div>
        <TwitterButton />
        </div>
    )
  }
componentDidMount() {
    fetch("https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json")
      .then(res => res.json())
      .then(
        (result) => {
          let i = this.state.quotePos;
          this.setState({
            quote: result.quotes[i].quote,
            author: result.quotes[i].author
          });
        },
        (error) => {
          this.setState({
            isLoaded: true,
            error
          });
        }
      )
  }
}

const QuoteBox = document.getElementById("quote-box")
ReactDOM.render(<QuoteBody />, QuoteBox);

我对React还是很陌生,所以我不确定自己做错了什么,所以我要分享整个项目。

我希望QuoteBody组件在运行refreshQuote时更新,但不会。

根据一些研究,我能收集到的最好的信息是,人们在异步执行操作时遇到相同的问题,但是我还没有找到解决我确切问题的清晰解决方案(我发现的大部分帮助是语法错误) ,我认为我没有了。

谢谢您的帮助-衷心感谢!

3 个答案:

答案 0 :(得分:2)

componentDidMount回调仅在组件安装在DOM中时运行,这是您首次加载页面的情况。状态的后续更改不会导致其再次安装。由于您要更改的只是状态的quotePos部分,因此quoteauthor部分不会更改,因此使用这些部分的部分将不会在以下渲染中更新。

您可能希望将整个结果集保持在状态componentDidMount中,并在渲染中使用quotePos读取正确的结果集。

答案 1 :(得分:1)

您应该调用fetch并在refreshQuote函数中更新逻辑。原因就是使用this.setState函数。首次加载组件后,将调用componentDidMount

componentDidMount类似于使用状态初始化组件。然后,当用户与组件交互时,您可以使用函数将事件从子组件传递给父组件。在上述情况下,该功能可以为refreshQuote

您还缺少将this绑定到组件的另一件事。使refreshQuote箭头功能。

您可以定义将状态更新到的自定义函数。否则,将提取逻辑添加到refreshQuote函数中。

答案 2 :(得分:0)

非常感谢!我在refreshQuote正文中进行了另一个访存调用。

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


  render(){
      return(
        <div>
          <a href="https://twitter.com/intent/tweet" id="tweet-quote">Tweet me</a>
        </div>
      )
    }
}

class QuoteBody extends React.Component{
  constructor(props){
    super(props)
    this.refreshQuote = this.refreshQuote.bind(this);
    this.state = { quote: "", author: "", quotePos: 0 };
  } 


refreshQuote() {
  fetch("https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json")
      .then(res => res.json())
      .then(
        (result) => {
          let i = this.state.quotePos;
          let n = Math.floor(Math.random() * (120 - 0 + 1) + 0);
          this.setState({
            quote: result.quotes[n].quote,
            author: result.quotes[n].author
          });
        },
        (error) => {
          this.setState({
            isLoaded: true,
            error
          });
        }
      )
  }


  render(){
    return(
      <div>
      <button id="new-quote" onClick={this.refreshQuote}>New Quote!</button>
      <div id="text"> 
      <p>{this.state.quote}</p>
        </div>
            <div id="author">
        <p>{"- " + this.state.author}</p>
        </div>
        <TwitterButton />
        </div>
    )
  }
componentDidMount() {
    fetch("https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json")
      .then(res => res.json())
      .then(
        (result) => {
          let n = Math.floor(Math.random() * (120 - 0 + 1) + 0);
          this.setState({
            quote: result.quotes[n].quote,
            author: result.quotes[n].author
          });
        },
        (error) => {
          this.setState({
            isLoaded: true,
            error
          });
        }
      )
  }
}

const QuoteBox = document.getElementById("quote-box")
ReactDOM.render(<QuoteBody />, QuoteBox);